Essential NPC's Auto healing?

Post » Tue Jun 19, 2012 3:13 am

Controlling and manipulating the players death has been one of the most frustrating and tedious tasks I've ever had to "luxury" of coding. It's funny, doing so was unreliable and buggy in Oblivion, and in Skyrim, we have way more commands and power at our disposal, yet it has proven to be just as difficult as it was before.

In a nutshell, I'm trying to create a script, that, upon the player's (or any Actor I attach the script to) death, they will come back to life. To accomplish this, I have set the player to be an essential NPC, and made him into a quest alias on my control quest. On his "OnEnterBleedOut()" Event, code is run to make it happen.

Scriptname Lich02QuestLichAliasScript extends ReferenceAlias  {This script alters the death of the Lich assuming he is a Type 02 Lich}Lich02QuestScript Property Lich02Quest AutoActor Property Lich AutoEvent OnInit()	; Set Lich Actor to Self	Lich = GetActorRef()EndEventEvent OnEnterBleedOut()	Utility.Wait(3.5)			; Let the Lich's ragdoll hit the ground	Lich02Quest.AdjustTargetHP(Lich, 15)	; Set Lich's health to 15EndEvent

The above uses a custom function within my Lich02Quest script. The code is as follows:
Function AdjustTargetHP(Actor Target, Float TargetHP)		; Acquire the Target's current HP	Float CurHP = Target.GetAV("Health")		; Adjust HP accordingly	If CurHP < TargetHP		; Target is lower than Target HP. Heal him		; Debug.MessageBox("Target is lower than Target health. Let's heal him.")		Target.RestoreAV("Health", TargetHP - CurHP)	Else				; Target is higher than Target HP, damage them		; Debug.MessageBox("Target is higher than Target health. Let's damage him.")		Target.DamageAV("Health", TargetHP - CurHP)		EndIf	EndFunction
So, upon running, if they have higher health than the number that was passed to the function, they will be damaged until they hit that specified value. If they were lower, they will be healed.

I use the AdjustHealth function to both bring an essential actor "back from the dead", and put them in a near death state.
On to the issue:

This all works perfectly the VERY FIRST TIME it is run. The actor dies, kneels over for a couple seconds (as per the Utility.Wait function), and then is healed to 15HP (Because he currently has negative health). However, upon his second "death", without the help of ANY code what so ever, he is restored to FULL hp immediately after he is thrown into the "OnEnterBleedOut" event.

This can even be tested using only console commands without the aid of the AdjustTargetHP method. That is to say, if you simply leave them hanging in in the IsBleedingOut state, they will stay that way forever. If you restore their hp using console commands, the exact same result will be produced. The only time the player actually "stays down" is on his first "death".

I couldn't figure out why this was happening, so I searched through the available actor functions to try and find a solution. I'd thought I found one.
Event OnEnterBleedOut()	Self.SetNoBleedoutRecovery(True)	; Prevent Actor from recovering from bleedout	Utility.Wait(3.5)			; Let the Lich's ragdoll hit the groundEndEvent

And it worked great! Upon his second death he did not restore to full hp. With the code I used above, I was merely trying to ensure he stayed down, so I had to bring him out of bleedout myself via RestoreAV Health command. However, it seems it was not quite as successful as I had hoped. The moment the player is restored above 1 HP, he is healed to full, regardless of the restore amount. I did some testing and this occurs regardless of whether it is done via console or script. No matter what, the very first "RestoreAV Health" that is run after entering the bleedout state, brings the player (and perhaps any target, though I haven't tested it on others yet.) above 1HP, he is healed to full.

Why does this happen, how can I stop it? I can't even seem to control it via scripts for some reason. They are healed to full no matter what I do. Any help appreciated...
User avatar
Jacob Phillips
 
Posts: 3430
Joined: Tue Aug 14, 2007 9:46 am

Post » Mon Jun 18, 2012 9:44 pm

Bump.
User avatar
Taylah Haines
 
Posts: 3439
Joined: Tue Feb 13, 2007 3:10 am

Post » Tue Jun 19, 2012 12:01 am

Hmm. Nobody knows anything?
User avatar
Lisa Robb
 
Posts: 3542
Joined: Mon Nov 27, 2006 9:13 pm

Post » Mon Jun 18, 2012 4:31 pm

Fourth time's the charm.

EDIT: Edited the main post for clarity. Hopefully that will increase my chances of a reply. <.<
User avatar
SexyPimpAss
 
Posts: 3416
Joined: Wed Nov 15, 2006 9:24 am

Post » Mon Jun 18, 2012 7:56 pm

My original hope when creating this thread was to see if anyone knew how to actually disable this event, but it does not seem as though anyone knows how. I honestly don't know what all is actually occurring during this "bleedout recovery", so I was hoping to avoid it all together.

However when re-wording my original post (and thus, thinking about the full process behind what seems to be happening), I found a solution. Here's my code:
; Adjust the Target's HP to a specified valueFunction AdjustTargetHP(Actor Target, Float TargetHP)		; This script operates on the assumption that the Target is essential, but it should essentially work for an NPC that isn't.	; If TargetHP is lower than 0 this script WILL kill them.	; The Target is essential so if done to him it will likely just leave him in a state of eternal death. (lul @ Lich joke)		; Acquire the Target's current HP	Float CurHP = Target.GetAV("Health")		If Target.IsBleedingOut() && CurHP > 0		; Target was probably killed via kill command or something similar.		; We will set CurHP to a negative value. However, remember that the target still has "positive" hp.		; Upon healing the target by any amount, they will be revived, probably to full hp automatically.		; Regardless, our BleedOutRecovery Counter should catch this and still adjust their health to the appropriate number				CurHP = CurHP * -1	EndIf		; BledOutRecovery Counter. If Target is being healed from death, we must first trigger the "bleedout recovery" health regen effect	If CurHP < 0		; Target is Dead. Heal him to 2 HP		Target.RestoreAV("Health", 2 - CurHP)		; BleedOutRecovery occurs once they are above 1HP.		CurHP = Target.GetAV("Health")			; Acquire the Target's new current HP.	EndIf		; Debug.Messagebox("Current Health: " + CurHP + " Target HP: " + TargetHP)		; Adjust HP so that it matches the TargetHP	If CurHP < TargetHP			; Target is lower than Target HP. Heal him		Target.RestoreAV("Health", TargetHP - CurHP)	Else					; Target is higher than Target HP. Damage him.		Target.DamageAV("Health", TargetHP - CurHP)	EndIf	EndFunction
User avatar
Yvonne
 
Posts: 3577
Joined: Sat Sep 23, 2006 3:05 am

Post » Tue Jun 19, 2012 2:14 am

Couple things that may help. Essential actors who are not in combat will automatically heal to max health very quickly - this is hardcoded. However, there is a function (SetNoBleedoutRecovery or something like that) which you can call on an actor to prevent them from recovering health automatically, which may be what you want to use since you want to manually control their healing through script.
User avatar
Dalley hussain
 
Posts: 3480
Joined: Sun Jun 18, 2006 2:45 am

Post » Mon Jun 18, 2012 4:12 pm

Couple things that may help. Essential actors who are not in combat will automatically heal to max health very quickly - this is hardcoded. However, there is a function (SetNoBleedoutRecovery or something like that) which you can call on an actor to prevent them from recovering health automatically, which may be what you want to use since you want to manually control their healing through script.
Thanks for the response. If all the bleedout recovery event does is heal the actor, then I have already developed a solution. A couple things I'd like to point out though, regarding the health restore.

You say that it happens when they are not in combat, but this was definitely occurring during combat. And, like I said, it would never happen on the "first" player bleedout event, but it would happen on every single event after the first. That is to say, if the player had entered bleedout at least once, he would continue to heal to max the moment he entered bleedout every single time. I did not try experimenting with starting combat against different actors after this occurred though.

If SetNoBleedoutRecovery is set to True, they will not recover from the bleedout event on their own. However the moment they are restored above 1HP (That is to say, at least 1.1 or possibly 2.0HP), the regeneration effect kicks in. The will still regenerate even though "SetNoBleedoutRecovery" is set to True. This is annoying, to say the least. I wonder if it was meant for it to function that way or not...
User avatar
jeremey wisor
 
Posts: 3458
Joined: Mon Oct 22, 2007 5:30 pm

Post » Mon Jun 18, 2012 12:46 pm

Hmm, maybe not too surprising, since once they're above 0 they're no longer in bleedout. (The auto-heal has to do with them being Essential/Protected, not to being in bleedout.)

I don't know of a way to prevent an essential actor from autohealing. I think it's hard-coded (it was occasionally annoying but we ended up being able to work around it).
User avatar
Samantha Pattison
 
Posts: 3407
Joined: Sat Oct 28, 2006 8:19 pm

Post » Mon Jun 18, 2012 4:07 pm

Essential actors when they reach 0 HP go into bleedout (kneel down) and cant be killed by anything, after a short moment they stand back up and are restored to full HP (in combat or not).

Try using the "protected" status instead of essential or making it so that they restore to full HP and then take damage equal to a %.

:bunny:
User avatar
krystal sowten
 
Posts: 3367
Joined: Fri Mar 09, 2007 6:25 pm

Post » Mon Jun 18, 2012 2:32 pm

'Protected' actors can still be killed by the player, so that may not work on his test dummies. For the player him/her self, however, it would be functionally identical, since you can't hurt yourself*.


*The player is considered an invalid target for his/her own attacks, and can't be hurt by them; death by trap or cliff is inflicted by the environment, not the player, and will not kill a Protected actor.

EDIT: I just remembered that there's a script concerning follower deaths that might be worth looking into. I haven't opened it myself so I don't know the contents, but there might be something useful there (I have a feeling not, but it's probably worth a look).
User avatar
Nienna garcia
 
Posts: 3407
Joined: Wed Apr 25, 2007 3:23 am

Post » Mon Jun 18, 2012 1:11 pm

Full disclosure: I'm a huge noob with programming so I might be totally out to lunch.

However, what I'm seeing is you're calling the function AdjustHealth(x,y) but you created a function AdjustTargetHP(x,y). What if you rename your function (the latter) to AdjustHealth(x,y)?

Or are those predefined calls?
User avatar
Eire Charlotta
 
Posts: 3394
Joined: Thu Nov 09, 2006 6:00 pm

Post » Mon Jun 18, 2012 1:33 pm

Full disclosure: I'm a huge noob with programming so I might be totally out to lunch.

However, what I'm seeing is you're calling the function AdjustHealth(x,y) but you created a function AdjustTargetHP(x,y). What if you rename your function (the latter) to AdjustHealth(x,y)?

Or are those predefined calls?
It was just a typo. I manually typed the code in my first example. It was supposed to be AdjustTargetHP.

EDIT: Just to clarify, I'd like to say that I no longer have a problem. The code I provided in Post #5 works just fine at solving the issue. As long as I use the AdjustTargetHP function after the essential actor's death, he will not heal to full.
User avatar
Deon Knight
 
Posts: 3363
Joined: Thu Sep 13, 2007 1:44 am


Return to V - Skyrim