Jump to content

[LE] Bleeding out when knocked down - help with a script


Recommended Posts

Hi everyone,

 

I've been working on a mod, that makes player essential and everything works perfectly fine until player dies when being knocked down. Normally, when player enters bleedout mode, he would bleed out for a few seconds and the would be teleported to a different location. But when he dies from i.e. unrelenting force or other attack which cause a player to be knocked down, he would stuck in some strange loop, being teleported to the same spot over and over(still lying on the floor unconscious), until finally would be transferred to correct location.

 

Here is the script fragment(more or less):

 

Game.DisablePlayerControls()
PlayerRef.SetNoBleedoutRecovery(True)
Utility.Wait(3.0)
PlayerRef.RemoveAllItems(Container, True, True)
Utility.wait(1.0)
FadeOut.Apply()
FadeOut.PopTo(FadeHold)


PlayerRef.SetNoBleedoutRecovery(False)
GetActorReference().ResetHealthAndLimbs()
MoveToLocation()
FadeHold.PopTo(FadeIn)
Game.EnablePlayerControls()

 

Does anyone know how to resolve this problem?

Link to comment
Share on other sites

If you have a fragment, so you have a quest. Next player alias script could be helpful to manage the issue you have with shouts. It is not completed, just a base to see what is happen with the player.

Maybe some shout trigger a special animation, you could catch that by using OnAnimationEvent() in the next script, but such animations have to be register before.

 

EssentialPlayerAliasScript

 

Scriptname EssentialPlayerAliasScript extends ReferenceAlias
{written by ReDragon 2017}    ; it needs a quest to get working

; https://forums.nexusmods.com/index.php?/topic/5526267-bleeding-out-when-knocked-down-help-with-a-script/

  Bool bHit
  Bool bBleedout


; -- EVENTs -- 4 + "Busy"

EVENT OnEnterBleedOut()
    Debug.Trace("EPA: OnEnterBleedOut() - player is bleeding out..")
    bBleedOut = TRUE
    gotoState("Done")                ; ### STATE ###
;--------------------
    actor aRef = self.GetActorReference()        ; = Game.GetPlayer()
    actorBase AB = aRef.GetActorBase()

    bool bProtected = AB.IsProtected()           ; test for actor protected flag
    AB.SetEssential(TRUE)        ; >>

    quest q = self.GetOwningQuest()
    WHILE aRef.IsBleedingOut() && (q) && q.IsRunning()
        aRef.RestoreActorValue("Health", Utility.RandomFloat(1.5, 3.0))
;;;     aRef.ResetHealthAndLimbs()
        Utility.Wait(1.0)
    ENDWHILE

    IF ( bProtected )
        AB.SetProtected(TRUE)
    ELSE
        AB.SetEssential(False)    ; <<
    ENDIF
;--------------------
    bBleedOut = False
    gotoState("")                    ; ### STATE ###
ENDEVENT

EVENT OnDying(Actor akKiller)
    Debug.Trace("EPA: OnDying() - player is dying.. The end is near.")
ENDEVENT

EVENT OnDeath(Actor akKiller)
    gotoState("Done")                ; ### STATE ###
    self.GetOwningQuest().Stop()
    Debug.Trace("EPA: OnDeath() - player has been killed!")
ENDEVENT


EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4)
IF ( bHit )
    RETURN    ; - STOP -    busy with action
ENDIF
;---------------------
IF (akAggressor as Actor)
ELSE
    RETURN    ; - STOP -    no actor, no shout
ENDIF
;---------------------
    bHit = TRUE
    myF_Action(akAggressor as Actor, akSource)
    bHit = False
ENDEVENT


;=====================
state Done
;=========
EVENT OnEnterBleedOut()
ENDEVENT

EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4)
ENDEVENT
;=======
endState


; -- FUNCTION --

FUNCTION myF_Action(Actor aRef, Form fm)
;---------------------------------------
    IF     (fm as Shout)
        Debug.Notification("- Player was hit by shout -")
    ELSEIF (fm as Spell)
        Debug.Notification("- Player was hit by magic -")
    ENDIF
ENDFUNCTION

 

 

Edited by ReDragon2013
Link to comment
Share on other sites

Wow, that looks compliacated :D (I'm kind of new to scripting maybe that's why).

The problem happens between "GetActorReference().ResetHealthAndLimbs()" and "MoveToLocation()". It's like the script can't trigger function "MoveToLocation()" when player is lying down unconscious. I tried to use different functions instead of ResetHealthAndLimbs(), but nothing I tried worked.

 

EDIT. After further testing it turns out it doesn't happen everytime. My guess is, the problem occures when player is taking damage while knocked down, but I'm not sure.

Edited by dailyplanet
Link to comment
Share on other sites

Your first posting contains that:

PlayerRef.SetNoBleedoutRecovery(False)
GetActorReference().ResetHealthAndLimbs()
MoveToLocation()

You did not provide enough information for me, to catch the troublemaker. Nevertheless it is very strange..

 

Let us assume playerRef is of type actor and contains the result of Game.GetPlayer().

 

Next line has self.GetActorReference(), which means the current script extends to ReferenceAlias. If that is TRUE and the script (you posted fragment here) is a player alias then self.GetActorReference() is the same as playerRef.

 

Last line MoveToLocation() is the same as self.MoveToLocation(), but this cannot work except it is a script internal function you have made.

 

Native functions are:

- MoveTo_-_ObjectReference

use that:

PlayerRef.SetNoBleedoutRecovery(False)
PlayerRef.ResetHealthAndLimbs()
PlayerRef.MoveTo(mRef)           ; mRef is a Xmarker where the player should be moved

these functions does not work for the player almost:

- MoveToIfUnloaded_-_ObjectReference player cannot unload, except player has died and then game reloads

- MoveToMyEditorLocation_-_ObjectReference player does not have an editor location

- MoveToPackageLocation_-_Actor maybe that could work, if player has a special package which is working in a specific location only

Edited by ReDragon2013
Link to comment
Share on other sites

MoveToLocation() is a function I made. It looks like that:

Function MoveToLocation()
If (Whiterun.IsChild(PlayerRef.GetCurrentLocation())) || (WhiterunHold.IsChild(PlayerRef.GetCurrentLocation())) || (Morthal.IsChild(PlayerRef.GetCurrentLocation())) || (HjaalmarchHold.IsChild(PlayerRef.GetCurrentLocation()))
PlayerRef.MoveTo(Reborn)
ElseIf (Solitude.IsChild(PlayerRef.GetCurrentLocation())) || (HaafingarHold.IsChild(PlayerRef.GetCurrentLocation()))
PlayerRef.MoveTo(RebornHaaf)
ElseIf (Markarth.IsChild(PlayerRef.GetCurrentLocation())) || (ReachHold.IsChild(PlayerRef.GetCurrentLocation()))
PlayerRef.MoveTo(RebornReach)

and so on.

 

I replaced all GetActorReference() and Game.GetPlayer() with PlayerRef, but the problem still persist. The situation when it happens is like a player keep dying after PlayerRef.ResetHealthAndLimbs(), so the script starts all over again before MoveToLocation() can even trigger, or because of that it fails to trigger.

Edited by dailyplanet
Link to comment
Share on other sites

It would save me a lot of time, if I got the info much earlier. Do you know location can be None as result of Game.GetPlayer().GetCurrentLocation()?

You have to cover that like the next functions, maybe it solves your issue.

 

 

 

;------------------------
FUNCTION MoveToLocation()
;------------------------
    location loc = PlayerRef.GetCurrentLocation()        ; location can be <None>
    IF ( loc )
        myF_MoveByLocation(loc)
    ELSE
        myF_MoveByCell(playerRef.GetParentCell())
    ENDIF
ENDFUNCTION


;-------------------------------------------------------------------------
Bool FUNCTION myF_IsMTL(Location hold, Location loc, ObjectReference mRef)  ; helper levvel 2
;-------------------------------------------------------------------------
;  (loc == Whiterun) || loc.IsChild(Whiterun)
IF (loc == hold) || loc.IsChild(hold)
    PlayerRef.MoveTo(mRef)
    Debug.Notification("MTL: Player moved to " +mRef)
    Return TRUE
ENDIF
;---------
    Return False
ENDFUNCTION

;----------------------------------------
FUNCTION myF_MoveByLocation(Location loc)  ; helper level 1
;----------------------------------------
IF myF_IsMTL(Whiterun, loc, Reborn)
    RETURN    ; - STOP - /1a
ENDIF
;---------------------
IF myF_IsMTL(WhiterunHold, loc, Reborn)
    RETURN    ; - STOP - /1b
ENDIF
;---------------------
IF myF_IsMTL(Morthal, loc, Reborn)
    RETURN    ; - STOP - /1c
ENDIF
;---------------------
IF myF_IsMTL(HjaalmarchHold, loc, Reborn)
    RETURN    ; - STOP - /1d
ENDIF
;---------------------

IF myF_IsMTL(Solitude, loc, RebornHaaf)
    RETURN    ; - STOP - /2a
ENDIF
;---------------------
IF myF_IsMTL(HaafingarHold, loc, RebornHaaf)
    RETURN    ; - STOP - /2b
ENDIF
;---------------------

IF myF_IsMTL(Markarth, loc, RebornReach)
    RETURN    ; - STOP - /3a
ENDIF
;---------------------
IF myF_IsMTL(ReachHold, loc, RebornReach)
    RETURN    ; - STOP - /3b
ENDIF
;---------------------
    Debug.Notification("No location found to moveto..")
ENDFUNCTION


;-------------------------------------------------------------------
Bool FUNCTION myF_IsMTC(Location hold, Cell c, ObjectReference mRef)  ; helper levvel 2
;-------------------------------------------------------------------
;  (playerRef.GetParentCell() == mRef.GetParentCell())
; http://www.creationkit.com/index.php?title=GetParentCell_-_ObjectReference

IF (c == mRef.GetParentCell())     ; If mRef is in an unloaded exterior cell, this function will return None.
    PlayerRef.MoveTo(mRef)
    Debug.Notification("MTc: Player moved to " +mRef)
    Return TRUE
ENDIF
;---------
    Return False
ENDFUNCTION

;------------------------------------
FUNCTION myF_MovePlayerByCell(Cell c)  ; helper level 1
;------------------------------------
IF myF_IsMTC(Whiterun, c, Reborn)
    RETURN    ; - STOP - /1a
ENDIF
;---------------------
IF myF_IsMTC(WhiterunHold, c, Reborn)
    RETURN    ; - STOP - /1b
ENDIF
;---------------------
IF myF_IsMTC(Morthal, c, Reborn)
    RETURN    ; - STOP - /1c
ENDIF
;---------------------
IF myF_IsMTC(HjaalmarchHold, c, Reborn)
    RETURN    ; - STOP - /1d
ENDIF
;---------------------

IF myF_IsMTC(Solitude, c, RebornHaaf)
    RETURN    ; - STOP - /2a
ENDIF
;---------------------
IF myF_IsMTC(HaafingarHold, c, RebornHaaf)
    RETURN    ; - STOP - /2b
ENDIF
;---------------------

IF myF_IsMTC(Markarth, c, RebornReach)
    RETURN    ; - STOP - /3a
ENDIF
;---------------------
IF myF_IsMTC(ReachHold, c, RebornReach)
    RETURN    ; - STOP - /3b
ENDIF
;---------------------
    Debug.Notification("ParentCell does not match..")

    worldspace w = playerRef.GetWorldSpace()
    Debug.Notification("Worldspace is " +w)    
ENDFUNCTION

{

 

Edited by ReDragon2013
Link to comment
Share on other sites

A way to check for multiple firings is to stick a global bool variable in your script, and use it as a flag to prevent multiple executions. Set it to false in the global declaration, set it to true at the beginning of your (rather long in realtime) respawn functions, set it to false after they complete.

 

EDIT:

If you want to get a count of the number of fires, you can also have an integer you increment (which can itself serve as the flag, but you'd lose the data on resetting on completion if you do that).

Edited by foamyesque
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...