Jump to content

[LE] Throttling OnHit scripts


lesi123

Recommended Posts

It's entirely possible that the stack dumps you're seeing have absolutely nothing to do with your script itself. You need to look through those logs and see what proportion of the stalled script instances are from your script. If there's really that much activity for the scripting system over a long time it may be getting overwhelmed by other scripts and systems and you're only seeing the problem because you're looking for something.

 

And are you still getting around 60 FPS during those battles or are you getting a substantial performance hit? Because raw FPS is critical to good Papyrus performance. If your framerate goes too low the system will start falling behind and eventually start giving those sorts of results.

Link to comment
Share on other sites

  • Replies 67
  • Created
  • Last Reply

Top Posters In This Topic

 

On the Cipscis site's example above, I simply replaced LongFunction with OnHit. I thought maybe it was serving an important purpose being there. :|

 

 

I remember seeing that site about three years ago and I could not make any sense of it. Now I am able to understand all of it. It is also interesting how he did what he did without having to created a waiting state. Thanks

 

Of course I have seen an event defined in the empty state. What a weird question.

 

That is not a weird question. I am talking about the busy "empty" state.

ScriptName LongFunctionScript extends ObjectReference


State Active 
Event OnHit
    GoToState("Busy")
    ; Do something that takes a long time
    GoToState("Active")
EndEvent
EndState
 
State Busy
; Do nothing  I have never seen a event defined here before. 
EndState
Edited by Masterofnet
Link to comment
Share on other sites

Well, I spoke too soon. I fought the dragon for longer this time (a little over 5 minutes) and ended up with stack dumps again, log at 3,285kb.

 

The script below is what I'm using. It takes longer to start dumping stacks but it seems to still have trouble keeping up.

 

 

It is a large script, however with the states added I think there may be other issues involved.

Edited by Masterofnet
Link to comment
Share on other sites

It's entirely possible that the stack dumps you're seeing have absolutely nothing to do with your script itself. You need to look through those logs and see what proportion of the stalled script instances are from your script. If there's really that much activity for the scripting system over a long time it may be getting overwhelmed by other scripts and systems and you're only seeing the problem because you're looking for something.

 

And are you still getting around 60 FPS during those battles or are you getting a substantial performance hit? Because raw FPS is critical to good Papyrus performance. If your framerate goes too low the system will start falling behind and eventually start giving those sorts of results.

 

I spawned the Sun Dragon with only USLEEP, SkyUI, MfgConsole, and Deadly Dragons and got no errors in my log after 5 minutes of being attacked. As soon as I load in my mod and do the same timed test, it's stack dumping with 1-2 thousand counts of this:

Frame count: 0 (Page count: 0)
State: Waiting on other stack for call (Freeze state: Freezing)
Type: Normal
Return register: None
Has stack callback: No
Stack trace:
[alias PlayerAlias on quest BTDQuestCREATUREtoPLAYERBleedDmg (0C01F387)].BTDCREATUREtoPLAYERDmg.OnHit() - (requested call)
[param 0]: None
[param 1]: [SPELL < (0D051BFF)>]
[param 2]: [PROJECTILE < (0200C610)>]
[param 3]: False
[param 4]: False
[param 5]: False
[param 6]: False

I've not seen any drop in FPS during battles either. Adding an empty OnHit event in the busy state is giving the same result.

 

The other instance of my script showing up in the log is 1 count of this:

Frame count: 1 (Page count: 1)
State: Running (Freeze state: Freezing)
Type: Normal
Return register: None
Has stack callback: No
Stack trace:
[alias PlayerAlias on quest BTDQuestCREATUREtoPLAYERBleedDmg (0C01F387)].BTDCREATUREtoPLAYERDmg.OnHit() - "BTDCREATUREtoPLAYERDmg.psc" Line 74
IP: 1374 Instruction: 41 Line: 74
[akAggressor]: None
[akSource]: [WEAPON < (000001F4)>]
[akProjectile]: None
[abPowerAttack]: False
[abSneakAttack]: False
[abBashAttack]: False
[abHitBlocked]: False
[::NoneVar]: None
[::temp0]: None
[::temp1]: None
[::temp2]: False
[::temp3]: None
[::temp4]: False
[::temp5]: None
[::temp6]: None
[::temp7]: False

and 1 count of this:

Frame count: 1 (Page count: 1)
State: Running (Freeze state: Freezing)
Type: Normal
Return register: None
Has stack callback: No
Stack trace:
[alias PlayerAlias on quest BTDQuestCREATUREtoPLAYERBleedDmg (0C01F387)].BTDCREATUREtoPLAYERDmg.OnHit() - "BTDCREATUREtoPLAYERDmg.psc" Line 74
IP: 1374 Instruction: 41 Line: 74
[akAggressor]: None
[akSource]: [SPELL < (0D051BFF)>]
[akProjectile]: [PROJECTILE < (0200C610)>]
[abPowerAttack]: False
[abSneakAttack]: False
[abBashAttack]: False
[abHitBlocked]: False
[::NoneVar]: None
[::temp0]: None
[::temp1]: None
[::temp2]: False
[::temp3]: None
[::temp4]: False
[::temp5]: None
[::temp6]: None
[::temp7]: False
Edited by lesi123
Link to comment
Share on other sites

 

 

On the Cipscis site's example above, I simply replaced LongFunction with OnHit. I thought maybe it was serving an important purpose being there. :|

 

 

I remember seeing that site about three years ago and I could not make any sense of it. Now I am able to understand all of it. It is also interesting how he did what he did without having to created a waiting state. Thanks

 

Of course I have seen an event defined in the empty state. What a weird question.

 

That is not a weird question. I am talking about the busy "empty" state.

ScriptName LongFunctionScript extends ObjectReference


State Active 
Event OnHit
    GoToState("Busy")
    ; Do something that takes a long time
    GoToState("Active")
EndEvent
EndState
 
State Busy
; Do nothing  I have never seen a event defined here before. 
EndState

 

I still don't understand the relevance. In the current example, the OnHit event is defined in the auto state and never in the empty state, which is the approach we are discussing.

Link to comment
Share on other sites

 

I still don't understand the relevance. In the current example, the OnHit event is defined in the auto state and never in the empty state, which is the approach we are discussing.

 

 

Have you not been reading the thread? Cooley has been saying that it needs to be or in some cases it will not work.

 

I am saying ( I have never seen that done before and I was wondering if anyone else has ).

 

From your previous answer are you indicating that you have seen it done that way before? Like this.

 

 

 

ScriptName LongFunctionScript extends ObjectReference


State Active
Event OnHit
GoToState("Busy")
; Do something that takes a long time
GoToState("Active")
EndEvent
EndState

State Busy
Event OnHit
; Do nothing
EndEvent
EndState

 

 

Edited by Masterofnet
Link to comment
Share on other sites

 

I spawned the Sun Dragon with only USLEEP, SkyUI, MfgConsole, and Deadly Dragons and got no errors in my log after 5 minutes of being attacked. As soon as I load in my mod and do the same timed test, it's stack dumping with 1-2 thousand counts of this:

 

Have you considered creating spells that perform these functions and placing them on the Race Template of NPCs? That may be much less taxing on your system.

Link to comment
Share on other sites

I do not want to interrupt your disput about states and flages, but sometimes it is a good idea to look at Bethesda wiki

http://www.creationkit.com/index.php?title=States_(Papyrus)

 

cdcooley, I do not hate states. Please edit your posting.

 

 

 

ScriptName LongFunctionScript extends ObjectReference
{This is a bad idea. Always use the state system above instead!}  
string busy = false;

Function LongFunction()
    if !busy
        busy = true
        ; Do something that takes a long time
        busy = false
    endif
EndFunction
ScriptName LongFunctionScript extends ObjectReference
{This is a legitim alternative to the states variant, not a bad script design.}
; "Always use the state system above instead!" <-- This is not right!!!

  Bool bBusy = False            ; boolVar not string

Function LongFunction()
if ( bBusy )
    RETURN    ; - STOP -    THREAD lock active
endif
;---------------------
    bBusy = TRUE    ; thread lock ON

    ; Do something that takes a long time

    bBusy = False    ; thread lock OFF
EndFunction

 

 

 

 

I also adjusted the player refAlias script a bit. Maybe it helps a bit to find the reason of stack error.

 

Scriptname BTDCREATUREtoPLAYERDmg extends ReferenceAlias
{rewritten by ReDragon 2016}    ; handles creature to Player bleed damage

; source: https://forums.nexusmods.com/index.php?/topic/5174600-throttling-onhit-scripts/page-4

;---------------------------------------------------------------------------------------------------------------------------------
; The HitChance conditions in the function blocks control the hit chances to apply the bleed damage spells to targets.
; To increase the chances of applying a bleed, use a lower number. To reduce the chances of applying a bleed, use a higher number.
;---------------------------------------------------------------------------------------------------------------------------------

  ;Actor Property PlayerRef Auto            ; DO NOT USE !!!

  Spell PROPERTY BTDSpellCREATURESmalltoPLAYERBleedDmg  auto
  Spell PROPERTY BTDSpellCREATUREMediumtoPLAYERBleedDmg auto
  Spell PROPERTY BTDSpellCREATURELargetoPLAYERBleedDmg  auto
  Spell PROPERTY BTDSpellCREATUREXLargetoPLAYERBleedDmg auto

  Keyword PROPERTY ActorTypeAnimal   auto
  Keyword PROPERTY ActorTypeCreature auto
  Keyword PROPERTY ActorTypeDwarven  auto

  Race PROPERTY DragonRace Auto
  Race PROPERTY WolfRace Auto
  Race PROPERTY SlaughterfishRace Auto
  Race PROPERTY SabreCatRace Auto
  Race PROPERTY SabreCatSnowyRace Auto
  Race PROPERTY BearBlackRace Auto
  Race PROPERTY BearBrownRace Auto
  Race PROPERTY BearSnowRace Auto
  Race PROPERTY IceWraithRace Auto
  Race PROPERTY WerewolfBeastRace Auto
  Race PROPERTY SprigganRace Auto
  Race PROPERTY SprigganMatronRace Auto
  Race PROPERTY TrollRace Auto
  Race PROPERTY TrollFrostRace Auto
  Race PROPERTY DwarvenSphereRace Auto
  Race PROPERTY DwarvenCenturionRace Auto
  Race PROPERTY SprigganEarthMotherRace Auto

; --- DLC1 ---
 ;Race Property DLC1DeathHoundRace Auto
 ;Race Property DLC1SabreCatGlowRace Auto
 ;Race Property DLC1GargoyleRace Auto
 ;Race Property DLC1GargoyleVariantBossRace Auto
 ;Race Property DLC1GargoyleVariantGreenRace Auto
 ;Race Property DLC1LD_ForgemasterRace Auto

; --- DLC2 ---
 ;Race Property DLC2SprigganBurntRace Auto
 ;Race Property DLC2WerebearBeastRace Auto
 ;Race Property DLC2DwarvenBallistaRace Auto
 ;Race Property DLC2dunKarstaagIceWraithRace Auto

 ;Actor Aggressor
 ;Race  AggressorRace
 ;Int   HitChance

; ***********************************************************************************************************************
; *** Note: Dragons and hagravens had to be excluded since their breaths and spells would apply bleeds to the player. ***
; ***********************************************************************************************************************


; -- EVENTs -- "Ready" + "Busy"

;=========================
Auto State Ready     ; HIT REGISTERED ON PLAYER
;===============
EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, Bool abPowerAttack, Bool abSneakAttack, Bool abBashAttack, Bool abHitBlocked)
IF ( abHitBlocked )                                 ; IF (abHitBlocked == true)
    RETURN    ; - STOP - /1    hit was blocked
ENDIF
;---------------------
IF (akSource as Spell)
    RETURN    ; - STOP - /2    spells are skipped
ENDIF
;---------------------
IF (akAggressor as Actor)
ELSE
    RETURN    ; - STOP - /3    no actor, no blood
ENDIF
;---------------------
IF (akSource as Weapon) ;|| (akProjectile)
ELSE
    RETURN    ; - STOP - /4    no weapon, no blood
ENDIF
;--------------------- all conditions above are thread safe
    gotoState("Busy")             ; ### STATE ### do not run this function again until it has finished

    PlayerHitBy(akAggressor as Actor)
        
    gotoState("Ready")             ; ### STATE ### function has finished back to auto state, it can be called again
ENDEVENT
;=======
endState


;=========================
State Busy    ; empty state, see also http://www.creationkit.com/index.php?title=States_(Papyrus)
;=========
;Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, Bool abPowerAttack, Bool abSneakAttack, Bool abBashAttack, Bool abHitBlocked)
;    ; Nothing
;EndEvent
;=======
endState


; -- FUNCTIONs -- 8

;-------------------------------
FUNCTION PlayerHitBy(Actor aRef)
;-------------------------------
    race r = aRef.GetRace()

IF (!r) || (r == DragonRace) ;|| (r.GetFormID() == 000131FB)        ; [RACE:000131FB] HagravenRace "Hagraven"
    RETURN    ; - STOP -    race is <None> or attack by dragon (or attack by Hagraven)
ENDIF
;---------------------
    spell sp

    IF     (aRef.HasKeyword(ActorTypeDwarven))
        sp = PlayerHitByDwarven(r)

    ELSEIF (aRef.HasKeyword(ActorTypeAnimal))
        sp = PlayerHitByAnimal(r)

    ELSEIF (aRef.HasKeyword(ActorTypeCreature))
        sp = PlayerHitByCreature(r)
    ENDIF

    IF ( sp )
        objectReference selfRef = self.GetReference()    ; = Game.GetPlayer() as ObjectReference        // its player alias script
;        #########################
;;;        sp.Cast(selfRef, selfRef)        ; THIS will cast a spell on the player over and over again !!!
;        #########################
        Debug.Trace("PlayerAlias: PlayerHitBy() - is casting " +sp+", aggressor was " +aRef)
    ENDIF
ENDFUNCTION


;---------------------------------------
Spell FUNCTION PlayerHitByAnimal(Race r)
;---------------------------------------
    int i = Utility.RandomInt()            ; = Utility.RandomInt(0,100)
    spell sp

IF     (r == WolfRace)
    sp = myF_GetSS(i, 70)                            ; small

ELSEIF (r == SlaughterfishRace)
    sp = myF_GetSS(i, 30)                            ; small

ELSEIF (r == SabreCatRace)
    sp = myF_GetSM(i, 60)                            ; medium

ELSEIF (r == SabreCatSnowyRace)
    sp = myF_GetSM(i, 50)                            ; medium

ELSEIF (r == BearBlackRace)
    sp = myF_GetSM(i, 50)                            ; medium

ELSEIF (r == BearBrownRace)
    sp = myF_GetSM(i, 60)                            ; medium

ELSEIF (r == BearSnowRace)
    sp = myF_GetSM(i, 50)                            ; medium

ELSEIF (r == TrollRace)
    sp = myF_GetSL(i, 60)                            ; large

ELSEIF (r == TrollFrostRace)
    sp = myF_GetSL(i, 50)                            ; large

ELSE
;========= DLC only =====
    int x = r.GetFormID()
    x = x % 0x00100000        ; convert to FormId without load order position

; DLC1SabreCatGlowRace [RACE:0200D0B6]  (r == DLC1SabreCatGlowRace)
    IF (x == 0x0000D0B6)
        sp = myF_GetSM(i, 50)                        ; medium
    ENDIF
ENDIF
;---------
    RETURN sp
ENDFUNCTION


;-----------------------------------------
Spell FUNCTION PlayerHitByCreature(Race r)
;-----------------------------------------
    int i = Utility.RandomInt()            ; = Utility.RandomInt(0,100)
    spell sp

IF     (r == IceWraithRace)
    sp = myF_GetSM(i, 50)                            ; medium

ELSEIF (r == WerewolfBeastRace)
    sp = myF_GetSL(i, 50)                            ; large

ELSEIF (r == SprigganRace)
    sp = myF_GetSL(i, 60)                            ; large

ELSEIF (r == SprigganMatronRace)
    sp = myF_GetSL(i, 50)                            ; large

ELSEIF (r == SprigganEarthMotherRace)
    sp = myF_GetSL(i, 40)                            ; large

; [RACE:000131F4] FalmerRace "Falmer"
; [RACE:000131F9] GiantRace "Giant"
; [VTYP:0001F21D] CrFrostbiteSpiderVoice
; [VTYP:0002AFD9] CrFrostbiteSpiderGiantVoice
; [VTYP:0001F152] CrChaurusVoice
ELSE
;========= DLC =====
    int x = r.GetFormID()
    x = x % 0x00100000        ; convert to FormId without load order position

; DLC1DeathHoundRace [RACE:0200C5F0]  (r == DLC1DeathHoundRace)
    IF     (x == 0x0000C5F0)
        sp = myF_GetSS(i, 70)                        ; small

; DLC1GargoyleRace [RACE:0200A2C6]  (r == DLC1GargoyleRace)
    ELSEIF (x == 0x0000A2C6)
        sp = myF_GetSL(i, 50)                        ; large

; DLC1GargoyleVariantGreenRace [RACE:02019D86] (r == DLC1GargoyleVariantGreenRace)
    ELSEIF (x == 0x00019D86)
        sp = myF_GetSL(i, 50)                        ; large

; DLC1GargoyleVariantBossRace [RACE:02010D00]  (r == DLC1GargoyleVariantBossRace)
    ELSEIF (x == 0x00010D00)
        sp = myF_GetSL(i, 40)                        ; large

; DLC2dunKarstaagIceWraithRace [RACE:03029EE7]    (r == DLC2dunKarstaagIceWraithRace)
    ELSEIF (x == 0x00029EE7)
        sp = myF_GetSM(i, 50)                        ; medium

; DLC2SprigganBurntRace [RACE:0301B644]     (r == DLC2SprigganBurntRace)
    ELSEIF (x == 0x0001B644)
        sp = myF_GetSL(i, 60)                        ; large

; DLC2WerebearBeastRace [RACE:0301E17B]  (r == DLC2WerebearBeastRace)
    ELSEIF (x == 0x0001E17B)
        sp = myF_GetSL(i, 50)                        ; large
    ENDIF

; [RACE:04017F44] DLC2RieklingRace
; [RACE:0401A50A] DLC2ThirskRieklingRace
; [RACE:04014495] DLC2LurkerRace "Giant"
ENDIF
;---------
    RETURN sp
ENDFUNCTION


;----------------------------------------
Spell FUNCTION PlayerHitByDwarven(Race r)
;----------------------------------------
    int i = Utility.RandomInt()            ; = Utility.RandomInt(0,100)
    spell sp

IF     (r == DwarvenSphereRace)
    sp = myF_GetSL(i, 50)                            ; large

ELSEIF (r == DwarvenCenturionRace)
    sp = myF_GetSX(i, 20)                            ; xlarge

ELSE
;========= DLC =====
    int x = r.GetFormID()
    x = x % 0x00100000        ; convert to FormId without load order position

; DLC1LD_ForgemasterRace [RACE:02015C34]  (r == DLC1LD_ForgemasterRace)
; DLC2DwarvenBallistaRace [RACE:0302B014] (r == DLC2DwarvenBallistaRace)
    IF (x == 0x00015C34) || (x == 0x0002B014)
        sp = myF_GetSX(i, 10)                        ; xlarge
    ENDIF
ENDIF
;---------
    RETURN sp    
ENDFUNCTION


;-------------------------------------------
Spell FUNCTION myF_GetSS(Int i, Int iChance)        ; small
;-------------------------------------------
IF (i >= iChance)
    RETURN BTDSpellCREATURESmalltoPLAYERBleedDmg
ENDIF
    RETURN None
ENDFUNCTION


;-------------------------------------------
Spell FUNCTION myF_GetSM(Int i, Int iChance)        ; medium
;-------------------------------------------
IF (i >= iChance)
    RETURN BTDSpellCREATUREMediumtoPLAYERBleedDmg
ENDIF
    RETURN None
ENDFUNCTION


;-------------------------------------------
Spell FUNCTION myF_GetSL(Int i, Int iChance)        ; large
;-------------------------------------------
IF (i >= iChance)
    RETURN BTDSpellCREATURELargetoPLAYERBleedDmg
ENDIF
    RETURN None
ENDFUNCTION


;-------------------------------------------
Spell FUNCTION myF_GetSX(Int i, Int iChance)        ; xLarge
;-------------------------------------------
IF (i >= iChance)
    RETURN BTDSpellCREATUREXLargetoPLAYERBleedDmg
ENDIF
    RETURN None
ENDFUNCTION

 

 

Link to comment
Share on other sites

I also adjusted the player refAlias script a bit. Maybe it helps a bit to find the reason of stack error.

 

 

Ya, You just made a few little adjustments. Great work man! I am going to be looking that over.

 

I do think the OnHit event should be shut down until all of the functions compete and I don't understand why you would go to state busy and then go right back to state ready.

 

I have updated your script a bit.

 

 

 

Scriptname BTDCREATUREtoPLAYERDmg extends ReferenceAlias
{rewritten by ReDragon 2016} ;Updated By The Big Man   ; handles creature to Player bleed damage

; source: Big Man Masterofnet

;---------------------------------------------------------------------------------------------------------------------------------
; The HitChance conditions in the function blocks control the hit chances to apply the bleed damage spells to targets.
; To increase the chances of applying a bleed, use a lower number. To reduce the chances of applying a bleed, use a higher number.
;---------------------------------------------------------------------------------------------------------------------------------

  ;Actor Property PlayerRef Auto            ; DO NOT USE !!!

  Spell PROPERTY BTDSpellCREATURESmalltoPLAYERBleedDmg  auto
  Spell PROPERTY BTDSpellCREATUREMediumtoPLAYERBleedDmg auto
  Spell PROPERTY BTDSpellCREATURELargetoPLAYERBleedDmg  auto
  Spell PROPERTY BTDSpellCREATUREXLargetoPLAYERBleedDmg auto

  Keyword PROPERTY ActorTypeAnimal   auto
  Keyword PROPERTY ActorTypeCreature auto
  Keyword PROPERTY ActorTypeDwarven  auto

  Race PROPERTY DragonRace Auto
  Race PROPERTY WolfRace Auto
  Race PROPERTY SlaughterfishRace Auto
  Race PROPERTY SabreCatRace Auto
  Race PROPERTY SabreCatSnowyRace Auto
  Race PROPERTY BearBlackRace Auto
  Race PROPERTY BearBrownRace Auto
  Race PROPERTY BearSnowRace Auto
  Race PROPERTY IceWraithRace Auto
  Race PROPERTY WerewolfBeastRace Auto
  Race PROPERTY SprigganRace Auto
  Race PROPERTY SprigganMatronRace Auto
  Race PROPERTY TrollRace Auto
  Race PROPERTY TrollFrostRace Auto
  Race PROPERTY DwarvenSphereRace Auto
  Race PROPERTY DwarvenCenturionRace Auto
  Race PROPERTY SprigganEarthMotherRace Auto

; --- DLC1 ---
 ;Race Property DLC1DeathHoundRace Auto
 ;Race Property DLC1SabreCatGlowRace Auto
 ;Race Property DLC1GargoyleRace Auto
 ;Race Property DLC1GargoyleVariantBossRace Auto
 ;Race Property DLC1GargoyleVariantGreenRace Auto
 ;Race Property DLC1LD_ForgemasterRace Auto

; --- DLC2 ---
 ;Race Property DLC2SprigganBurntRace Auto
 ;Race Property DLC2WerebearBeastRace Auto
 ;Race Property DLC2DwarvenBallistaRace Auto
 ;Race Property DLC2dunKarstaagIceWraithRace Auto

 ;Actor Aggressor
 ;Race  AggressorRace
 ;Int   HitChance

; ***********************************************************************************************************************
; *** Note: Dragons and hagravens had to be excluded since their breaths and spells would apply bleeds to the player. ***
; ***********************************************************************************************************************


; -- EVENTs -- "Ready" + "Busy"

;=========================
Auto State Ready     ; HIT REGISTERED ON PLAYER
;===============
EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, Bool abPowerAttack, Bool abSneakAttack, Bool abBashAttack, Bool abHitBlocked)
gotoState("Busy") 
IF ( abHitBlocked ) || (akSource as Spell) || !(akAggressor as Actor) || !(akSource as Weapon)  ; I do not know how this script is going to fire on animal hits when it is shut down if the hit does not come from a weapon??? 
   gotoState("Ready")
   RETURN   
Else
    PlayerHitBy(akAggressor as Actor)
EndIf
ENDEVENT
;=======
endState


;=========================
State Busy    ; empty state, see also http://www.creationkit.com/index.php?title=States_(Papyrus)
;=========
;Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, Bool abPowerAttack, Bool abSneakAttack, Bool abBashAttack, Bool abHitBlocked)
;    ; Nothing
;EndEvent
;=======
endState


; -- FUNCTIONs -- 8

;-------------------------------
FUNCTION PlayerHitBy(Actor aRef)
;-------------------------------
    race r = aRef.GetRace()

IF (!r) || (r == DragonRace) || (r.GetFormID() == 000131FB)        ; [RACE:000131FB] HagravenRace "Hagraven"
    gotoState("Ready")
    RETURN    ; - STOP -    race is <None> or attack by dragon (or attack by Hagraven)
ENDIF
;---------------------
    spell sp

    IF     (aRef.HasKeyword(ActorTypeDwarven))
        sp = PlayerHitByDwarven(r)

    ELSEIF (aRef.HasKeyword(ActorTypeAnimal))
        sp = PlayerHitByAnimal(r)

    ELSEIF (aRef.HasKeyword(ActorTypeCreature))
        sp = PlayerHitByCreature(r)
    ENDIF

    IF ( sp )
        Actor selfRef = self.GetReference As Actor()   ; = Game.GetPlayer() as Actor        // its player alias script
;        #########################
;;;        sp.Cast(selfRef, selfRef)        ; THIS will cast a spell on the player over and over again !!!
;        #########################
        Debug.Trace("PlayerAlias: PlayerHitBy() - is casting " +sp+", aggressor was " +aRef)
    ENDIF
ENDFUNCTION


;---------------------------------------
Spell FUNCTION PlayerHitByAnimal(Race r)
;---------------------------------------
    int i = Utility.RandomInt()            ; = Utility.RandomInt(0,100)
    spell sp

IF     (r == WolfRace)
    sp = myF_GetSS(i, 70)                            ; small

ELSEIF (r == SlaughterfishRace)
    sp = myF_GetSS(i, 30)                            ; small

ELSEIF (r == SabreCatRace)
    sp = myF_GetSM(i, 60)                            ; medium

ELSEIF (r == SabreCatSnowyRace)
    sp = myF_GetSM(i, 50)                            ; medium

ELSEIF (r == BearBlackRace)
    sp = myF_GetSM(i, 50)                            ; medium

ELSEIF (r == BearBrownRace)
    sp = myF_GetSM(i, 60)                            ; medium

ELSEIF (r == BearSnowRace)
    sp = myF_GetSM(i, 50)                            ; medium

ELSEIF (r == TrollRace)
    sp = myF_GetSL(i, 60)                            ; large

ELSEIF (r == TrollFrostRace)
    sp = myF_GetSL(i, 50)                            ; large

ELSE
;========= DLC only =====
    int x = r.GetFormID()
    x = x % 0x00100000        ; convert to FormId without load order position

; DLC1SabreCatGlowRace [RACE:0200D0B6]  (r == DLC1SabreCatGlowRace)
    IF (x == 0x0000D0B6)
        sp = myF_GetSM(i, 50)                        ; medium
    ENDIF
ENDIF
;---------
    RETURN sp
ENDFUNCTION


;-----------------------------------------
Spell FUNCTION PlayerHitByCreature(Race r)
;-----------------------------------------
    int i = Utility.RandomInt()            ; = Utility.RandomInt(0,100)
    spell sp

IF     (r == IceWraithRace)
    sp = myF_GetSM(i, 50)                            ; medium

ELSEIF (r == WerewolfBeastRace)
    sp = myF_GetSL(i, 50)                            ; large

ELSEIF (r == SprigganRace)
    sp = myF_GetSL(i, 60)                            ; large

ELSEIF (r == SprigganMatronRace)
    sp = myF_GetSL(i, 50)                            ; large

ELSEIF (r == SprigganEarthMotherRace)
    sp = myF_GetSL(i, 40)                            ; large

; [RACE:000131F4] FalmerRace "Falmer"
; [RACE:000131F9] GiantRace "Giant"
; [VTYP:0001F21D] CrFrostbiteSpiderVoice
; [VTYP:0002AFD9] CrFrostbiteSpiderGiantVoice
; [VTYP:0001F152] CrChaurusVoice
ELSE
;========= DLC =====
    int x = r.GetFormID()
    x = x % 0x00100000        ; convert to FormId without load order position

; DLC1DeathHoundRace [RACE:0200C5F0]  (r == DLC1DeathHoundRace)
    IF     (x == 0x0000C5F0)
        sp = myF_GetSS(i, 70)                        ; small

; DLC1GargoyleRace [RACE:0200A2C6]  (r == DLC1GargoyleRace)
    ELSEIF (x == 0x0000A2C6)
        sp = myF_GetSL(i, 50)                        ; large

; DLC1GargoyleVariantGreenRace [RACE:02019D86] (r == DLC1GargoyleVariantGreenRace)
    ELSEIF (x == 0x00019D86)
        sp = myF_GetSL(i, 50)                        ; large

; DLC1GargoyleVariantBossRace [RACE:02010D00]  (r == DLC1GargoyleVariantBossRace)
    ELSEIF (x == 0x00010D00)
        sp = myF_GetSL(i, 40)                        ; large

; DLC2dunKarstaagIceWraithRace [RACE:03029EE7]    (r == DLC2dunKarstaagIceWraithRace)
    ELSEIF (x == 0x00029EE7)
        sp = myF_GetSM(i, 50)                        ; medium

; DLC2SprigganBurntRace [RACE:0301B644]     (r == DLC2SprigganBurntRace)
    ELSEIF (x == 0x0001B644)
        sp = myF_GetSL(i, 60)                        ; large

; DLC2WerebearBeastRace [RACE:0301E17B]  (r == DLC2WerebearBeastRace)
    ELSEIF (x == 0x0001E17B)
        sp = myF_GetSL(i, 50)                        ; large
    ENDIF

; [RACE:04017F44] DLC2RieklingRace
; [RACE:0401A50A] DLC2ThirskRieklingRace
; [RACE:04014495] DLC2LurkerRace "Giant"
ENDIF
;---------
    RETURN sp
ENDFUNCTION


;----------------------------------------
Spell FUNCTION PlayerHitByDwarven(Race r)
;----------------------------------------
    int i = Utility.RandomInt()            ; = Utility.RandomInt(0,100)
    spell sp

IF     (r == DwarvenSphereRace)
    sp = myF_GetSL(i, 50)                            ; large

ELSEIF (r == DwarvenCenturionRace)
    sp = myF_GetSX(i, 20)                            ; xlarge

ELSE
;========= DLC =====
    int x = r.GetFormID()
    x = x % 0x00100000        ; convert to FormId without load order position

; DLC1LD_ForgemasterRace [RACE:02015C34]  (r == DLC1LD_ForgemasterRace)
; DLC2DwarvenBallistaRace [RACE:0302B014] (r == DLC2DwarvenBallistaRace)
    IF (x == 0x00015C34) || (x == 0x0002B014)
        sp = myF_GetSX(i, 10)                        ; xlarge
    ENDIF
ENDIF
;---------
    RETURN sp    
ENDFUNCTION


;-------------------------------------------
Spell FUNCTION myF_GetSS(Int i, Int iChance)        ; small
;-------------------------------------------
IF (i >= iChance)
    gotoState("Ready")
    RETURN BTDSpellCREATURESmalltoPLAYERBleedDmg
ENDIF
    gotoState("Ready")
    RETURN None
ENDFUNCTION


;-------------------------------------------
Spell FUNCTION myF_GetSM(Int i, Int iChance)        ; medium
;-------------------------------------------
IF (i >= iChance)
    gotoState("Ready")
    RETURN BTDSpellCREATUREMediumtoPLAYERBleedDmg
ENDIF
    gotoState("Ready")
    RETURN None
ENDFUNCTION


;-------------------------------------------
Spell FUNCTION myF_GetSL(Int i, Int iChance)        ; large
;-------------------------------------------
IF (i >= iChance)
    gotoState("Ready")
    RETURN BTDSpellCREATURELargetoPLAYERBleedDmg
ENDIF
    gotoState("Ready")
    RETURN None
ENDFUNCTION


;-------------------------------------------
Spell FUNCTION myF_GetSX(Int i, Int iChance)        ; xLarge
;-------------------------------------------
IF (i >= iChance)
    gotoState("Ready")
    RETURN BTDSpellCREATUREXLargetoPLAYERBleedDmg
ENDIF
    gotoState("Ready")
    RETURN None
ENDFUNCTION 

 

 

Edited by Masterofnet
Link to comment
Share on other sites

If you get a stack dump I would expect one or two instances of the script to appear somewhere, the problem is that you seem to have more than that. Does the scripting system recover after the combat is over? Stack dumps aren't inherently a critical problem, they just mean the scripting system isn't keeping up with all of the action. Your mod is adding more scripting activity to an already heavy load and you're trying to stress it out so it does make sense you can trigger them.

 

Maybe the problem is related to the fact that you're casting a spell on the player (which has its own hit effect) and under heavy load the game isn't getting that fully processed until after the state has changed, but even if that were the case there shouldn't be a way for multiple cases to stack up. There's also a chance you've got some sort of locking problem which is preventing scripts from completing. If the scripting system eventually stops applying the effect and then doesn't recover after combat is over that would be the most likely problem.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...