Jump to content

[LE] Why does my script crash?


Recommended Posts

That algebra means nothing to me without knowing what it's doing and the values of the variables, but a freeze generally suggests that something is recursive. Are you using any while loops based around this? Or if you are using OnUpdate() based on this timer - if it's resulting in a very low number then you're possibly refreshing the function too quickly, like millisecond often. Also, be sure to differentiate between a crash and a freeze; in the case of the latter, the game is still running but is busy doing its eternal thing - just make sure you shut the game down before it runs out of memory and overflows the buffer.

Edited by Kapteyn
Link to comment
Share on other sites

This is the whole script:

 

RIght now, it usually sets the timer to 0.41something the first time round.

The next time it should update, it freezes - nothing happens, I can't even close the game in the task manager.

 

I'm working on having it show me how long it took to run through the script's main part. if it's more than 0.05, that might confuse things.

Edit: it was 0.0000043 - not the reason.

 

It seems that updates after more than 0.4 - the value I've set for pHourstoWait - make the game freeze.

 

 

ScriptName HungerCounterScript extends activemagiceffect

Float Property pHoursToWait Auto
Float TimerSetting
GlobalVariable Property HungerCount Auto
GlobalVariable Property HungerCount01 Auto
GlobalVariable Property HungerCount02 Auto
GlobalVariable Property HungerCount03 Auto
MagicEffect Property HungerEffect01 Auto
MagicEffect Property HungerEffect02 Auto
MagicEffect Property HungerEffect03 Auto
Spell Property HungerSpell01 Auto
Spell Property HungerSpell02 Auto
Spell Property HungerSpell03 Auto
Float NewTime
Float StartTime
GlobalVariable Property MasterCounterHunger Auto
GlobalVariable Property MasterCounterInterval Auto

Event OnUpdateGameTime()
; debug.trace(self + "OnUpdateGameTime")
Debug.Notification("Update")
NewTime = Utility.GetCurrentGameTime()
MasterCounterInterval.GetValue()
MasterCounterInterval.SetValue(math.floor(math.floor(NewTime*24-StartTime*24)/pHoursToWait))
If MasterCounterHunger.GetValueInt() < MasterCounterInterval.GetValueInt()
HungerCount.Mod(MasterCounterInterval.GetValueInt()-MasterCounterHunger.GetValueInt())
MasterCounterHunger.SetValue(MasterCounterInterval.GetValueInt())
Endif
Debug.Notification("pHourstoWait has passed" + (math.floor(math.floor(NewTime*24-StartTime*24)/pHoursToWait)) + "whole times since StartTime")
Debug.Notification("The next update should happen in" + ((1+MasterCounterInterval.GetValueInt())*pHoursToWait-(NewTime*24-StartTime*24)) + "")
If ((1+MasterCounterInterval.GetValueInt())*pHoursToWait-(NewTime*24-StartTime*24)) > 0.05
TimerSetting = ((1+MasterCounterInterval.GetValueInt())*pHoursToWait-(NewTime*24-StartTime*24))
Else
TimerSetting = ((2+MasterCounterInterval.GetValueInt())*pHoursToWait-(NewTime*24-StartTime*24))
HungerCount.Mod(1.0)
Endif
RegisterForUpdateGameTime(TimerSetting)
Debug.Notification("Timer set to" + TimerSetting + "")
if HungerCount.GetValue() >= HungerCount03.GetValue()
If (Game.GetPlayer().HasMagicEffect(HungerEffect03))
else
Game.GetPlayer().AddSpell(HungerSpell03, false)
Debug.Notification("You are starving.")
endif
If (Game.GetPlayer().HasMagicEffect(HungerEffect02))
Game.GetPlayer().RemoveSpell(HungerSpell02)
endif
If (Game.GetPlayer().HasMagicEffect(HungerEffect01))
Game.GetPlayer().RemoveSpell(HungerSpell01)
endif
elseif HungerCount.GetValue() >= HungerCount02.GetValue()
If (Game.GetPlayer().HasMagicEffect(HungerEffect02))
else
Game.GetPlayer().AddSpell(HungerSpell02, false)
Debug.Notification("You are hungry.")
endif
If (Game.GetPlayer().HasMagicEffect(HungerEffect03))
Game.GetPlayer().RemoveSpell(HungerSpell03)
endif
If (Game.GetPlayer().HasMagicEffect(HungerEffect01))
Game.GetPlayer().RemoveSpell(HungerSpell01)
endif
elseif HungerCount.GetValue() >= HungerCount01.GetValue()
If (Game.GetPlayer().HasMagicEffect(HungerEffect01))
else
Game.GetPlayer().AddSpell(HungerSpell01, false)
Debug.Notification("You have an appetite.")
endif
If (Game.GetPlayer().HasMagicEffect(HungerEffect03))
Game.GetPlayer().RemoveSpell(HungerSpell03)
endif
If (Game.GetPlayer().HasMagicEffect(HungerEffect02))
Game.GetPlayer().RemoveSpell(HungerSpell02)
endif
elseif HungerCount.GetValue() < HungerCount01.GetValue()
If (Game.GetPlayer().HasMagicEffect(HungerEffect01))
Game.GetPlayer().RemoveSpell(HungerSpell01)
endif
If (Game.GetPlayer().HasMagicEffect(HungerEffect03))
Game.GetPlayer().RemoveSpell(HungerSpell03)
endif
If (Game.GetPlayer().HasMagicEffect(HungerEffect02))
Game.GetPlayer().RemoveSpell(HungerSpell02)
endif
endif
EndEvent

Event OnEffectStart(Actor akTarget, Actor akCaster)
; start timer
StartTime = Utility.GetCurrentGameTime()
TimerSetting = pHoursToWait
RegisterForUpdateGameTime(TimerSetting)
EndEvent

 

 

ALso, I don't know how to post one of the beautiful, colorful scripts I see aorund here sometimes. Sorry for the block of text.

Edited by TangerineDog
Link to comment
Share on other sites

Aieee, indent your code, it'll make your life much easier. The colourful formatting you're talking about is done with the [plain]

[/plain] tags, FYI.

 

I am not certain but I suspect the culprit is some kind of recursion between your adding of spells and your OnEffectStart event. I would try remarking out the entire block of if statements governing what hunger spell should be applicable and seeing what happens. Your internal debug statements should probably be converted from Notification to Trace as well; they're faster and the logfile will give you much more precise timestamps and ordering. You'll probably want to prefix them with "TangerineHunger" or something so that you can find them in all the other junk the logfile can have, though.

Link to comment
Share on other sites

Aieee, indent your code, it'll make your life much easier. The colourful formatting you're talking about is done with the [plain]

[/plain] tags, FYI.

 

I am not certain but I suspect the culprit is some kind of recursion between your adding of spells and your OnEffectStart event. I would try remarking out the entire block of if statements governing what hunger spell should be applicable and seeing what happens. Your internal debug statements should probably be converted from Notification to Trace as well; they're faster and the logfile will give you much more precise timestamps and ordering. You'll probably want to prefix them with "TangerineHunger" or something so that you can find them in all the other junk the logfile can have, though.

 

It might have been indented. The BB system doesn't handle pasted tab indents properly most of the time. Which is why my editors are all configured (when possible) to convert tabs to spaces. You also forgot to close the code tag in your example.

Link to comment
Share on other sites

RegisterForUpdateGameTime() again and again.. Maybe the next code is useful for you.

 

HungerCounterScript

 

Scriptname HungerCounterScript extends ActiveMagicEffect
{rewritten by ReDragon 2017}

; https://forums.nexusmods.com/index.php?/topic/6050258-why-does-my-script-crash/
;  TangerineDog wrote: " ((1+MasterCounterInterval.GetValueInt())*pHoursToWait-(NewTime*24-StartTime*24)) "
;        "It sets a timer to this value, but when it's time for that update, the game just freezes."

  GlobalVariable PROPERTY MasterCounterInterval auto
  GlobalVariable PROPERTY MasterCounterHunger   auto
  GlobalVariable PROPERTY HungerCount   auto
  GlobalVariable PROPERTY HungerCount01 auto
  GlobalVariable PROPERTY HungerCount02 auto
  GlobalVariable PROPERTY HungerCount03 auto

  Spell PROPERTY HungerSpell01 auto
  Spell PROPERTY HungerSpell02 auto
  Spell PROPERTY HungerSpell03 auto

  MagicEffect PROPERTY HungerEffect01 auto
  MagicEffect PROPERTY HungerEffect02 auto
  MagicEffect PROPERTY HungerEffect03 auto

  Float PROPERTY pHoursToWait auto
  Float StartTime


; -- EVENTs -- 3

EVENT OnEffectStart(Actor akTarget, Actor akCaster)
;IF (akCaster == Game.GetPlayer())
    Debug.Trace("HungerME: OnEffectStart() - target = " +akTarget+ ", caster = " +akCaster)        ; info only
    StartTime = Utility.GetCurrentGameTime()
    RegisterForSingleUpdateGameTime(pHoursToWait)              ; single update here, keep in mind !!!
;ENDIF
ENDEVENT


EVENT OnEffectFinish(Actor akTarget, Actor akCaster)
    Debug.Trace("HungerME: OnEffectFinish() - target = " +akTarget+ ", caster = " +akCaster)    ; info only
ENDEVENT


EVENT OnUpdateGameTime()
    float f = myF_Timer()
    myF_Hunger()
    RegisterForSingleUpdateGameTime(f)                          ; register again for gametime update
ENDEVENT


; -- FUNCTIONs -- 2

;-------------------------
Float FUNCTION myF_Timer()
;-------------------------
    float fCurrent = Utility.GetCurrentGameTime()               ; fCurrent = NewTime
    float fTimer   = (fCurrent - StartTime) * 24                ; fTimer = TimerSetting

    float f = fTimer / pHoursToWait
    MasterCounterInterval.SetValue(f)                           ; from here: f == MasterCounterInterval.GetValue()

    IF (MasterCounterHunger.GetValue() < f)
        HungerCount.Mod(f - MasterCounterHunger.GetValue())
        MasterCounterHunger.SetValue(f)
    ENDIF

    IF ( ((1+f)*pHoursToWait - fTimer) > 0.05 )
        fTimer = ((1+f)*pHoursToWait - fTimer)
    ELSE
        fTimer = ((2+f)*pHoursToWait - fTimer)
        HungerCount.Mod(1.0)
    ENDIF

    Debug.Trace("HungerME: OnUpdateGameTime() - HungerCount = " +HungerCount.GetValue())
    Debug.Notification("Timer = " +fTimer)

    RETURN fTimer
ENDFUNCTION


;--------------------
FUNCTION myF_Hunger()
;--------------------
    actor Player = Game.GetPlayer()
    float f = HungerCount.GetValue()                     ; take it once, store the value

IF (f >= HungerCount03.GetValue())
    IF Player.HasMagicEffect(HungerEffect03)
        ; HungerSpell03 already here
    ELSE
        Player.AddSpell(HungerSpell03, False)
        Debug.Notification("You are starving.")          ; 03 starving
    ENDIF

    Player.RemoveSpell(HungerSpell01)
    Player.RemoveSpell(HungerSpell02)
    RETURN    ; - STOP -
ENDIF
;---------------------
IF (f >= HungerCount02.GetValue())
    IF Player.HasMagicEffect(HungerEffect02)
        ; HungerSpell02 already here
    ELSE
        Player.AddSpell(HungerSpell02, False)
        Debug.Notification("You are hungry.")            ; 02 hungry
    ENDIF

    Player.RemoveSpell(HungerSpell01)
    Player.RemoveSpell(HungerSpell03)
    RETURN    ; - STOP -
ENDIF
;---------------------
IF (f >= HungerCount01.GetValue())
    IF Player.HasMagicEffect(HungerEffect01)
        ; HungerSpell01 already here
    ELSE
        Player.AddSpell(HungerSpell01, False)
        Debug.Notification("You have an appetite.")      ; 01 appetite
    ENDIF

    Player.RemoveSpell(HungerSpell02)
    Player.RemoveSpell(HungerSpell03)
    RETURN    ; - STOP -
ENDIF
;---------------------
;IF (f < HungerCount01.GetValue())
    Player.RemoveSpell(HungerSpell01)
    Player.RemoveSpell(HungerSpell02)
    Player.RemoveSpell(HungerSpell03)
;ENDIF
ENDFUNCTION

 

 

Link to comment
Share on other sites

RegisterForUpdateGameTime() again and again.. Maybe the next code is useful for you.

 

HungerCounterScript

 

Scriptname HungerCounterScript extends ActiveMagicEffect
{rewritten by ReDragon 2017}

; https://forums.nexusmods.com/index.php?/topic/6050258-why-does-my-script-crash/
;  TangerineDog wrote: " ((1+MasterCounterInterval.GetValueInt())*pHoursToWait-(NewTime*24-StartTime*24)) "
;        "It sets a timer to this value, but when it's time for that update, the game just freezes."

  GlobalVariable PROPERTY MasterCounterInterval auto
  GlobalVariable PROPERTY MasterCounterHunger   auto
  GlobalVariable PROPERTY HungerCount   auto
  GlobalVariable PROPERTY HungerCount01 auto
  GlobalVariable PROPERTY HungerCount02 auto
  GlobalVariable PROPERTY HungerCount03 auto

  Spell PROPERTY HungerSpell01 auto
  Spell PROPERTY HungerSpell02 auto
  Spell PROPERTY HungerSpell03 auto

  MagicEffect PROPERTY HungerEffect01 auto
  MagicEffect PROPERTY HungerEffect02 auto
  MagicEffect PROPERTY HungerEffect03 auto

  Float PROPERTY pHoursToWait auto
  Float StartTime


; -- EVENTs -- 3

EVENT OnEffectStart(Actor akTarget, Actor akCaster)
;IF (akCaster == Game.GetPlayer())
    Debug.Trace("HungerME: OnEffectStart() - target = " +akTarget+ ", caster = " +akCaster)        ; info only
    StartTime = Utility.GetCurrentGameTime()
    RegisterForSingleUpdateGameTime(pHoursToWait)              ; single update here, keep in mind !!!
;ENDIF
ENDEVENT


EVENT OnEffectFinish(Actor akTarget, Actor akCaster)
    Debug.Trace("HungerME: OnEffectFinish() - target = " +akTarget+ ", caster = " +akCaster)    ; info only
ENDEVENT


EVENT OnUpdateGameTime()
    float f = myF_Timer()
    myF_Hunger()
    RegisterForSingleUpdateGameTime(f)                          ; register again for gametime update
ENDEVENT


; -- FUNCTIONs -- 2

;-------------------------
Float FUNCTION myF_Timer()
;-------------------------
    float fCurrent = Utility.GetCurrentGameTime()               ; fCurrent = NewTime
    float fTimer   = (fCurrent - StartTime) * 24                ; fTimer = TimerSetting

    float f = fTimer / pHoursToWait
    MasterCounterInterval.SetValue(f)                           ; from here: f == MasterCounterInterval.GetValue()

    IF (MasterCounterHunger.GetValue() < f)
        HungerCount.Mod(f - MasterCounterHunger.GetValue())
        MasterCounterHunger.SetValue(f)
    ENDIF

    IF ( ((1+f)*pHoursToWait - fTimer) > 0.05 )
        fTimer = ((1+f)*pHoursToWait - fTimer)
    ELSE
        fTimer = ((2+f)*pHoursToWait - fTimer)
        HungerCount.Mod(1.0)
    ENDIF

    Debug.Trace("HungerME: OnUpdateGameTime() - HungerCount = " +HungerCount.GetValue())
    Debug.Notification("Timer = " +fTimer)

    RETURN fTimer
ENDFUNCTION


;--------------------
FUNCTION myF_Hunger()
;--------------------
    actor Player = Game.GetPlayer()
    float f = HungerCount.GetValue()                     ; take it once, store the value

IF (f >= HungerCount03.GetValue())
    IF Player.HasMagicEffect(HungerEffect03)
        ; HungerSpell03 already here
    ELSE
        Player.AddSpell(HungerSpell03, False)
        Debug.Notification("You are starving.")          ; 03 starving
    ENDIF

    Player.RemoveSpell(HungerSpell01)
    Player.RemoveSpell(HungerSpell02)
    RETURN    ; - STOP -
ENDIF
;---------------------
IF (f >= HungerCount02.GetValue())
    IF Player.HasMagicEffect(HungerEffect02)
        ; HungerSpell02 already here
    ELSE
        Player.AddSpell(HungerSpell02, False)
        Debug.Notification("You are hungry.")            ; 02 hungry
    ENDIF

    Player.RemoveSpell(HungerSpell01)
    Player.RemoveSpell(HungerSpell03)
    RETURN    ; - STOP -
ENDIF
;---------------------
IF (f >= HungerCount01.GetValue())
    IF Player.HasMagicEffect(HungerEffect01)
        ; HungerSpell01 already here
    ELSE
        Player.AddSpell(HungerSpell01, False)
        Debug.Notification("You have an appetite.")      ; 01 appetite
    ENDIF

    Player.RemoveSpell(HungerSpell02)
    Player.RemoveSpell(HungerSpell03)
    RETURN    ; - STOP -
ENDIF
;---------------------
;IF (f < HungerCount01.GetValue())
    Player.RemoveSpell(HungerSpell01)
    Player.RemoveSpell(HungerSpell02)
    Player.RemoveSpell(HungerSpell03)
;ENDIF
ENDFUNCTION

 

 

That doesn't freeze!

I do not yet see what's the difference in function between my chaotic script and your elegant work of art, but I'll get there after some sleep and/ or more caffeine.

 

I made some changes however:

first, in function myF_Timer, I added a floor: float f = math.floor(fTimer / pHoursToWait), because the master counter should only count how many whole times the interval has passed.

second, in funktion myF_timer, I added MasterCounterHunger.Mod(1.0) below HungerCount.Mod(1.0) to prevent redundancy.

 

RIght now, it seems to work peachily (is that a word?). It shall have to be playtested tomorrow.

 

For now, thank you!

 

edited to fix typo

Edited by TangerineDog
Link to comment
Share on other sites

The general rule with the update function is that the recurring updates often need a way out. If you don't have an exit for it, you essentially have an infinite loop which is not always a bad thing if the updates are occurring with enough time between them, but you sometimes still want that option available to exit. This is why a single update, followed by another single update in the update function itself, is the way to go. You then use a global variable which can be flipped either in the MCM or using the console (set <variable> to <float>) - so you have a condition in the script insomuch that if the variable is zero then the update will not occur. I hope that makes sense, it's kinda difficult to explain without enough, like you say, caffeine.

Link to comment
Share on other sites

ALso, I don't know how to post one of the beautiful, colorful scripts I see aorund here sometimes. Sorry for the block of text.

You need to use the CODE tag not just the SPOILER tag. You can nest code tags inside of the spoiler tag when you want both. The code tag is what keeps the spacing and gives the pretty colors. The spoiler tag isn't really even that important here. Hiding big blocks of text in spoiler tags is useful in general threads, but when the entire thread is about a particular script it makes sense to just post that script and only use the code tag.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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