Enemy that only doesn't block the player - how?
Moderator: GZDoom Developers
Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.
Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.
Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
Enemy that only doesn't block the player - how?
I'm sure there will be an easy answer to this and I'm sure it's been asked before but I can find it.
What's the best way to make an enemy that has normal blocking behaviour as far as everything in the game is concerned, but with one exception: players can walk right through as if it did not have the SOLID flag?
I'd prefer if the answer was for DECORATE because I'm using it on an existing actor, though if the only possibility is ZScript, I could convert it.
Thanks.
What's the best way to make an enemy that has normal blocking behaviour as far as everything in the game is concerned, but with one exception: players can walk right through as if it did not have the SOLID flag?
I'd prefer if the answer was for DECORATE because I'm using it on an existing actor, though if the only possibility is ZScript, I could convert it.
Thanks.
Re: Enemy that only doesn't block the player - how?
Only possible with ZScript.
Code: Select all
class LOLZombieMan : ZombieMan replaces ZombieMan
{
override bool CanCollideWith(Actor other, bool passive)
{
if (passive && other && other is "PlayerPawn")
{
return false;
}
return true;
}
}
- Void Weaver
- Posts: 724
- Joined: Thu Dec 18, 2014 7:15 am
- Contact:
Re: Enemy that only doesn't block the player - how?
What about using the same species as Player +THRUSPECIES flag?
Re: Enemy that only doesn't block the player - how?
Nash's code worked for me and the actor is now converted to ZScript too.
Thanks.
Thanks.
Re: Enemy that only doesn't block the player - how?
Just a thought, seeing as how this has now moved across to ZScript, would it be possible to write a custom code pointer for this actor that checks of a player is inside/touching it and, if the answer is no, then sets itself to be impassable to players too?
For a bit of context, the actor is a sentry gun (adapted from the ones in Stronghold) that is placed by the player via an inventory item. I was having all sorts of problems with the player getting stuck inside the spawned weapons, or the spawns failing or whatever. Making them non-solid to players solved all that because I can now spawn them exactly where the player is standing: if there is room for the player, there is room for the gun.
The icing on the cake would be if the gun could check to see if the player was still within its radius and if not, it could become solid to players too. The thing is, I have no idea how to do that, but it strikes me as something that might be possible.
For a bit of context, the actor is a sentry gun (adapted from the ones in Stronghold) that is placed by the player via an inventory item. I was having all sorts of problems with the player getting stuck inside the spawned weapons, or the spawns failing or whatever. Making them non-solid to players solved all that because I can now spawn them exactly where the player is standing: if there is room for the player, there is room for the gun.
The icing on the cake would be if the gun could check to see if the player was still within its radius and if not, it could become solid to players too. The thing is, I have no idea how to do that, but it strikes me as something that might be possible.
- Matt
- Posts: 9696
- Joined: Sun Jan 04, 2004 5:37 pm
- Preferred Pronouns: They/Them
- Operating System Version (Optional): Debian Bullseye
- Location: Gotham City SAR, Wyld-Lands of the Lotus People, Dominionist PetroConfederacy of Saudi Canadia
- Contact:
Re: Enemy that only doesn't block the player - how?
I too would like to know if there's a simple built-in way to see if two arbitrarily selected actors' hitboxes are intersecting each other. If there is, then the sentry could just check that against its owner (or any colliding player) every so often and set a flag/give a CanCollideWith result accordingly.
I can imagine using if(min(abs(pos.x-other.pos.x),abs(pos.y-other.pos.y))>radius+other.radius) but I have this feeling that there's something better in native code somewhere.
I can imagine using if(min(abs(pos.x-other.pos.x),abs(pos.y-other.pos.y))>radius+other.radius) but I have this feeling that there's something better in native code somewhere.
Re: Enemy that only doesn't block the player - how?
Maybe spawn the turret with the -SOLID flag, and add something like this in the Tick function?
It's not technically as precise a check as what you're asking for - it checks for map geometry also - and I have no idea how intensive that check is, or if this will actually work in practice... I've done something similar to spawn effect-only actors with bNoInteraction, then unsetting that flag once the actor is clear of any other actor so that collision is restored with other actors or map geometry.
Code: Select all
if (!bSolid) { bSolid = TestMobjLocation(); }
- Graf Zahl
- Lead GZDoom+Raze Developer
- Posts: 49067
- Joined: Sat Jul 19, 2003 10:19 am
- Location: Germany
Re: Enemy that only doesn't block the player - how?
That won't work with portals anyway. You have to calculate the distance vector with the provided functions.Matt wrote: I can imagine using if(min(abs(pos.x-other.pos.x),abs(pos.y-other.pos.y))>radius+other.radius) but I have this feeling that there's something better in native code somewhere.
- Matt
- Posts: 9696
- Joined: Sun Jan 04, 2004 5:37 pm
- Preferred Pronouns: They/Them
- Operating System Version (Optional): Debian Bullseye
- Location: Gotham City SAR, Wyld-Lands of the Lotus People, Dominionist PetroConfederacy of Saudi Canadia
- Contact:
Re: Enemy that only doesn't block the player - how?
So no shortcut option involving a blockmap check then? (assuming that would be computationally less expensive than multiple portal-sensitive distance and square roots every tick)
Re: Enemy that only doesn't block the player - how?
I tried to get that working (tried a few different ways) but I'm a complete ZScript n00b so I never managed to even get something that would run.AFADoomer wrote:Maybe spawn the turret with the -SOLID flag, and add something like this in the Tick function?Code: Select all
if (!bSolid) { bSolid = TestMobjLocation(); }
Have you got an example actor where you use this that I could look at?
Re: Enemy that only doesn't block the player - how?
Here's a quick and dirty example... I couldn't get it to work with SOLID, but changing the NOBLOCKMAP flag does what you want, I think...
Give yourself the "Dropper" item, then use the inventory item to spawn a "Dropped" tech lamp right in front of you that is effectively non-solid until you move away.
Give yourself the "Dropper" item, then use the inventory item to spawn a "Dropped" tech lamp right in front of you that is effectively non-solid until you move away.
Code: Select all
version "4.2"
class Dropper : Inventory
{
Default
{
+INVENTORY.INVBAR
}
States
{
Spawn:
UNKN A -1;
Stop;
}
override bool Use(bool pickup)
{
if (owner) { Spawn("Dropped", owner.pos + RotateVector((8, 0), owner.angle)); }
return Super.Use(pickup);
}
}
class Dropped : TechLamp2
{
Default
{
+NOBLOCKMAP // Start out with other actors ignoring you for collision purposes
}
override void Tick()
{
if (bNoBlockMap && TestMobjLocation()) { A_ChangeLinkFlags(0); } // If the NOBLOCKMAP flag is set, but the actor's position is now valid, unset the flag.
Super.Tick();
}
}
Re: Enemy that only doesn't block the player - how?
OK, I think I can follow that. I can't check it right now, but I'll take a proper look tomorrow. Thank you.
Re: Enemy that only doesn't block the player - how?
Better solution, based on Nash's initial response:
This has the same apparent effect on the player (lamp spawns inside player radius but doesn't interfere with movement until you move outside of the lamp's radius), but this also lets projectiles still hit the lamp after you spawn it, even while the player is still overlapping with it... So you can drop this and hide from, say, imp projectiles behind it.
Code: Select all
class Dropped : TechLamp2
{
override bool CanCollideWith(Actor other, bool passive)
{
if (passive && other && other is "PlayerPawn" && !TestMobjLocation())
{
return false;
}
return true;
}
}
Re: Enemy that only doesn't block the player - how?
I was just about to check the earlier version when I saw your post. It works perfectly. It does what I originally wanted (which is what Nash's code did, of course) and extends it to cover my secondary goal too so that the dropped item makes more sense in the world (i.e. as soon as you move away, it behaves just like any other solid obstacle).
Thank you.
Thank you.