![]() |
Immortal Zombie (reaver armor) with the gunshot wounds to the head to prove it. |
Zombies That Magically Heal
Sometimes zombies just don't want to die, even when you shoot them in the head numerous times. In the case of the Reaver style zombies (encFeralGhoul04), they get knocked down and then get back up with full health restored. This is the zombie type I've personally noticed this bug with and it is 100% repeatable with them. All other zombie variants die as expected with a headshot.
Tracking Down the Issue
Tracking this down involved a lot of trial and error, but eventually it came down to what I believe to be a bug in the game with Deferred Kill and this particular Feral Ghoul actor type. Deferred Kill basically makes it so an actor does not die until you tell it to. If headshots only mode is enabled, then deferred kill is started when the zombie is initialized.
To end the deferred kill, I registerd for the OnCripple event. This event is triggered when any limb (including the head) is crippled by damage. I noticed for the Reaver style armored zombies that this event was triggering twice and that the deferred kill seemed to not be honored.
Event OnCripple(ActorValue akActorValue, bool abCrippled)
[ZombieEffectScript] HandleCrippleEvent([Actor < (FF00134A)>],[ActorValue <PerceptionCondition (0000036C)>],True) -> 0.000000
[ZombieEffectScript] HandleCrippleEvent([Actor < (FF00134A)>],[ActorValue <PerceptionCondition (0000036C)As you can see above, the first call has 'True' for the crippled bool flag for the PerceptionCondition (head) which is good. In that handler I EndDeferredKill and then call Kill if the actor is still alive. This apparently isn't good enough for the Reaver zombies as they regenerated their health and limbs, did NOT end deferred kill and got back up off the ground. This regeneration is what I think triggers the second onCripple event which notifies the code that the head is now un-crippled (abCripple is 'False').>],False) -> 100.000000
After some experimenting in game, I noticed that you could in fact kill these zombies if you shot it multiple times in the head in succession (while it was dropping to the ground). I then experimented with shooting them in the torso a bit first and then the head which revealed a pretty consistent way to dispatch them as they died almost always with a single head shot if their health was down a bit first.
Fixing the Problem
As an experiment, I updated my onCripple handler to remove any remaining health before ending the deferred kill state and that fixed the issue. Apparently triggering EndDeferredKill when their remaining health was 0 always worked for the Reavers, even though the other types didn't care how much health was remaining. I think it wasn't the EndDeferredKill call itself so much as the subsequent call to Kill that seemed to behave differently.Here's what I ended up with:
; helper function to handle both onCripple and onPartialCripple
Function HandleCrippleEvent(Actor akSender, ActorValue akActorValue, bool abCrippled)
Debug.OpenUserLog("joefor")
Debug.TraceUser("joefor", "[ZombieEffectScript] HandleCrippleEvent(" + akSender + "," + akActorValue+ "," + abCrippled + ") -> " + akSender.GetValue(akActorValue))
If( abCrippled )
If( akActorValue == HeadConditionAV )
; head is crippled - make sure zombie dies
KillZombie()
Else
; other body part crippled - apply knockdown
ZombieActor.PushActorAway(ZombieActor, 1)
NPCFeralGhoulInjuredDownNotOutEnter.Play(ZombieActor)
EndIf
EndIf
EndFunction
Function KillZombie()
float healthAmount = ZombieActor.GetValue(HealthAV)
Debug.OpenUserLog("joefor")
Debug.TraceUser("joefor", "[ZombieEffectScript] KillZombie(" + ZombieActor + ", health=" + healthAmount)
; there's a bug with Feral Ghoul 04 not dying if health remains before deferred kill ends
; make sure remaining health is zero to trigger deferred kill
ZombieActor.DamageValue( HealthAV, healthAmount )
; end deferred kill to allow zombie to die
ZombieActor.EndDeferredKill()
; now, make sure zombie dies
If( !ZombieActor.IsDead() )
ZombieActor.Kill()
EndIf
EndFunction
Version 1.15 Coming Soon
I'm wrapping up some testing and will be deploying in the next day or so. Here's what will be included:- The fix described above for immortal zombies
- fix for Suffolk County Charter School (humans in underwear spawning instead of zombies)
- NEW optional horde behavior - zombies follow each other and wander around instead of standing still where they spawned (I may blog separately about this)
Update 1/1/2017: more immortal zombies
![]() |
More immortal zombies, one of which is missing half its skull. |
Another immortal zombie bug was reported and has been fixed. This one has to do with situations where the OnCripple event is not received by the script and therefore the zombie never leaves the deferred kill state. Subsequent OnCripple events are not received for the head if you continue to shoot the head.
To reproduce this, I used a missile launcher and aimed for the chest in a group of zombies. The immense amount of damage seems to sometimes cause this. I'm still not 100% sure why the OnCripple for the head (PerceptionCondition) is not received by the script. I noticed that every time it happens, the script does receive OnCripple for the body (EnduranceCondition). Maybe the game assumes if the torso is crippled (which is rare) then the creature will die anyway so it doesn't bother sending a separate one for the head?
In either case, to fix the problem I added one more event registration to the script. This one is for the OnDeferredKill event. This event gets triggered when an actor is in the deferred kill state and receives damage that would kill it if it weren't in that state. It also happens to fire over and over again as damage is received, even if the health goes into the negatives. Basically, I use this function to check the state of the head and end deferred kill if it is destroyed.
Let's hope this is the last of the stubborn zombies that refuse to die.
Update 1/27/2017: crippled vs dismembered
Even after my last update, still some immortal zombies were reported albeit rarely and usually when using certain explosive weapons like Spray N' Pray. Upon further research I noticed that in VATS only their torso was target-able as in the screenshot below.
![]() |
Immortal zombie with only the torso target-able in VATS. |
I began doing research into what would cause the head to not be there and quickly realized that it is actually dismembered (like the legs/arms in the screenshot above). After adding some debug logging I then saw that sometimes the head health would be above zero even though the head was dismembered!
OnDeferredKill([Actor < (FF000F36)>],[Actor < (00000014)>]), PerceptionCondition = 20.053139, HeadDismembered = TrueI then updated my function to check if the head is destroyed by checking EITHER:
- Head health is 0 (PerceptionCondition) ... OR ...
- Head is dismembered (Head1 for feral ghouls and humans)
I then tested by spawning groups of 20-30 zombies at a time, waiting a bit for my scripts to attach and initialize on all of them, and then mowing them down with Spray N' Pray. Before the changes I was seeing 1 or 2 in every group in the immortal state in the screenshot above. After the change I could not produce a single occurrence even after spawning several waves.
0 comments: