Eventually I came across this thread, in which OP was asking about a method for achieving headshots which centered around spawning invisible child actors which would act as hitboxes, mainly using A_SpawnItemEx. With a little tweaking, this worked! After I first posted this tutorial, board member Mikk- showed me some things that could be used to greatly improve the system. So far I've successfully applied it to two monsters, and I'd like to demonstrate how it's done.
The OP of the aforementioned thread, CaptainToenail, called his sample monster TestZombie, and I think that's a pretty good name. So start by declaring a new actor that inherits the attributes of a Former Human, ZombieMan. You can import his attributes pretty much wholesale; the only thing we'll need to modify in the monster definition itself are States.
Code: Select all
ACTOR TestZombie : ZombieMan replaces ZombieMan
{
States
{
Spawn:
TNT1 AA 0 A_SpawnItemEx("HeadshotHitbox", 0,0,0, 0,0,0, 0, SXF_SETMASTER)
Goto Super::Spawn
Death.HeadShot:
POSS HHHHH 0 A_SpawnItemEx("Blood",0,0,45,frandom(-2.0,2.0),frandom(-2.0,2.0),frandom(1.5,5.0))
POSS H 2
POSS I 2 A_Scream
POSS J 2
POSS K 2
POSS L -1 A_NoBlocking
Stop
}
}
Then we declared a zero-duration blank frame using A_SpawnItemEx to spawn our headshot hitbox. We're setting the item to be spawned as "HeadshotHitbox", giving zeroes for all offsets (we'll set the correct offsets in the hitbox definition, which will override any set here), zeroes for all x, y, and z-velocities, zero angle, and a flag of SXF_SETMASTER, which ties the headshot hitbox to our monster in a child/master relationship.
"Goto Super::Spawn" allows us to only spawn one hitbox actor, one time, per monster. This custom spawn state will execute, then this command will cause execution control to move to this actor's parent class (vanilla ZombieMan), specifically its Spawn state.
This final bit here, the Death.HeadShot state, is a custom DamageType state. This isn't necessary for the headshot to function, but you can use it to add a custom headshot death animation. Without it the headshot kill will still work, it will just result in an instant death with a normal animation. Thanks to Mikk for the extra blood splattering effect achieved with A_SpawnItemEx (and if you know a simple way to cause extra blood DECALS to spawn, please let me know!)
...
Now let's define our hitbox actor, which will look like this:
Code: Select all
ACTOR HeadshotHitbox
{
Radius 21
Health 1
Height 8
Mass 0x7FFFFFFF
+SHOOTABLE
+NOGRAVITY
+NODAMAGETHRUST
States
{
Spawn:
TNT1 A 1 A_Warp(AAPTR_MASTER, 0,0,45, 0, WARPF_INTERPOLATE|WARPF_NOCHECKPOSITION)
TNT1 A 0 A_CheckFlag("SOLID", "Spawn", AAPTR_MASTER)
RemoveActor:
TNT1 A 0 A_Remove(AAPTR_DEFAULT)
Stop
Death:
TNT1 A 0 A_KillMaster("HeadShot")
Stop
}
}
Health is set to 1 for instant kills; height is the hitbox's vertical size; a Mass of 0x7FFFFFFF will render the hitbox immune to game physics; and keep the NODAMAGETHRUST flag on, or your zombie will fly across the room upon death.
For our states, Spawn first needs to call A_Warp. AAPTR_MASTER codepoints the hitbox actor to the monster actor as its Master, set 45 for the z-offset, and the above flags for keeping the hitbox securely attached to the monster in the correct position.
What's happening next, with A_CheckFlag, is another very cool thing Mikk suggested. A_CheckFlag takes three arguments. The first is the flag to be checked. If this flag is TRUE, or on (+), execution will jump to the state (of the calling actor, in this case HeadshotHitbox) indicated in the SECOND argument. The third, optional (but not for us), argument accepts a codepointer indicating which actor to check the flag indicated in the first argument.
So, here A_CheckFlag looks at the SOLID flag in TestZombie (as pointed to by argument #3, AAPTR_DEFAULT), and if it's True, it returns to the top of its own Spawn state, refreshing A_Warp. Now that's just sexy. But it gets better! If SOLID returns as False -- which will happen when TestZombie enters its death state and calls A_NoBlocking, control will not return to the top of the Spawn state, but instead will drop through to our custom State, RemoveActor. This calls A_Remove which we've told to remove the calling actor, itself, HeadshotHitbox, and ensures its deletion with the death of the monster.
If you want the custom death animation for headshots we talked about before, call A_KillMaster in your hitbox's Death state and give it the name of your custom damage type in quotations.
...
That's really about it. For testing, if you need to do so, I found it helpful to set a few custom properties. For one, have the monster's health very high and his speed very low. 500 and 1, respectively, were good for me. That way you can check for the headshot hitbox and body hitbox's boundaries with precision, and set the speed so you're not giving yourself a headache trying to aim at zigzagging Zombie Men.
In the headshot hitbox definition, if you set the BloodColor property to green, or another vividly non-red color, you'll be able to clearly discern between hitting the monster's body and head. Also if you set the Spawn state to a visible frame (we found BAL2A0 useful) and set the RenderStyle property to something like 'Add' (additive) or 'Shadow', you'll have a convenient visual approximation of the hitbox's center.
If you're anything like me, and you just want to get the thing done, and not have to spend a whole bunch of time digging through years of scraps of information (even if that can be kind of fun in itself =P) then I hope this eases your suffering a bit. If you have any specific questions or know of any way to improve this tutorial, or just feel like saying hi! .. feel free to post here or PM me. G'day.