Jump to content

Script Review


Recommended Posts

@dylbill that much better))) but it is still way unnecessary complicated, mine vanilla,  even negative is possible with vanilla.  So nothing changed... and I still stand by that,  you could that with out SKSE

Spoiler
string Function DecimalToHexadecimalVanilla(int decimal) Global

    bool bNegative

    if (decimal < 0)
        decimal * -1
        bNegative = true
    ElseIf decimal == 0
        Return "0x0"
    EndIf

    string[] letters = new string[6]
    letters[0]="A"
    letters[1]="B"
    letters[2]="C"
    letters[3]="D"
    letters[4]="E"
    letters[5]="F"

    string hexadecimal = ""
    while (decimal > 0)
        int remainder = decimal % 16
        if remainder < 10
            hexadecimal = remainder As string + hexadecimal
        Else
            hexadecimal = letters[remainder - 10] + hexadecimal
        EndIf
        decimal /= 16
    endwhile
    If !bNegative
        return "0x" + hexadecimal
    EndIf
    return "-0x" + hexadecimal
EndFunction

 

 a vanilla one what returns a negative with one loop, here my go to comment I always use, your all over thinking stuff.. good code is simple. .  your using four loops and call four SKSE functions respectively 

Just for fun a SKSE one I hope you notice I am NOT using a string, but the ascii table..  and math.. ( had to explain that cos that code missing on the creation kit  wikki) so it is all me, just take my word for it, if you trust me

https://www.ibm.com/docs/en/aix/7.2?topic=adapters-ascii-decimal-hexadecimal-octal-binary-conversion-table

Spoiler
string Function DecimalToHexadecimalSKSE(int decimal) Global

    bool bNegative

    if (decimal < 0)
        decimal * -1
        bNegative = true
    ElseIf decimal == 0
        Return "0x0"
    EndIf

    string hexadecimal = ""
    while (decimal > 0)
        int remainder = decimal % 16
        if remainder < 10
            hexadecimal = remainder As string + hexadecimal
        Else
            hexadecimal = StringUtil.AsChar(remainder + 55) + hexadecimal
        EndIf
        decimal /= 16
    endwhile
    If !bNegative
        return "0x" + hexadecimal
    EndIf
    return "-0x" + hexadecimal
EndFunction 

 

I do not care if offend you again they were writing code like children, see the difference when it is done right with the ascii table

Link to comment
Share on other sites

@dylbill here a hint for you what the difference between upper case and lower case ? 1 flipped bit, they did that intentionally to make it easy to change it))))

1000001 = A
1100001 = a

but it works for all of them, just the second from the left is flipped 

There more to coding than Bethesda 

Link to comment
Share on other sites

Posted (edited)

I'm almost done with the mod, and I want to share the final scripts with you. The scripts seem to be working well. After running for 60 seconds, the player can't run for 180 seconds, but this can be ended by sleeping or using options in the Magic > Powers menu. These options include animations like sitting and lying down, which also apply to followers. Please let me know if you have any comments or suggestions.

Scriptname modRunningFatiguePlayerScript extends ReferenceAlias  

Actor PlayerRef
Float currentCarryWeight
Int runningCounter 
Int fatigueCounter
Bool bOnFatigue 

Function StartFatigue()
  currentCarryWeight = PlayerRef.GetActorValue("CarryWeight")
  PlayerRef.DamageActorValue("CarryWeight", currentCarryWeight)
  runningCounter = 0
  bOnFatigue = true
EndFunction

Function StopFatigue()
  PlayerRef.RestoreActorValue("CarryWeight", currentCarryWeight)
  runningCounter = 0
  fatigueCounter = 0
  bOnFatigue = false
EndFunction

Function StartWarningFatigue() ;This is to warn the player when they are close to entering the fatigue state.
  currentCarryWeight = PlayerRef.GetActorValue("CarryWeight")
  PlayerRef.DamageActorValue("CarryWeight", currentCarryWeight)
  Utility.Wait(4)
  PlayerRef.RestoreActorValue("CarryWeight", currentCarryWeight)
EndFunction

Event OnInit()
  PlayerRef = Game.GetPlayer()
  bOnFatigue = false
  runningCounter = 0
  fatigueCounter = 0
  RegisterForSleep()
  RegisterForSingleUpdate(3.0)
EndEvent

Event OnUpdate()
  if bOnFatigue == true
    fatigueCounter+=5
  elseif PlayerRef.IsRunning() && !PlayerRef.IsInCombat() && !PlayerRef.IsSneaking()
    runningCounter+=5
  endif
	
  if runningCounter == 45
    runningCounter = 50 ;If the player doesn't run and, therefore, the counter doesn't increase, then startWarningFatigue will be executed in every update. Setting runningCounter to 50 prevents this.
    StartWarningFatigue()
  endif

  if runningCounter >= 60 ;The player can exceed the 60-second time limit by sprinting. However, once sprinting stops, they enter the fatigue state.
    if !PlayerRef.IsSprinting()
      StartFatigue()
    endif
  endif

  if fatigueCounter == 180
    StopFatigue()
  endif

  RegisterForSingleUpdate(5.0)
EndEvent

Event OnSleepStop(bool abInterrupted)
  StopFatigue()
EndEvent

This is the script of one of the resting options accessible from the Magic > Powers menu.

Scriptname aaaModRestSpellAScript extends activemagiceffect  

Idle Property IdleSitCrossLeggedExit Auto
modRunningFatiguePlayerScript Property pModRunningFatiguePlayerScript Auto
FollowerAliasScript Property pFollowerAliasScript Auto
Actor PlayerRef

Event OnInit()
  PlayerRef = Game.GetPlayer()
EndEvent

Event OnEffectStart(Actor akTarget, Actor akCaster)
  Game.SetPlayerAIDriven()
  Game.DisablePlayerControls(0,1,0,0,1,0,1)
  Debug.SendAnimationEvent(PlayerRef, "IdleSitCrossLeggedEnter")
  Utility.Wait(0.7) ;This is to make it realistic, by playing the follower's animation shortly after the player's.
  Actor FollowerActor = pFollowerAliasScript.GetActorRef() as Actor
  Debug.SendAnimationEvent(FollowerActor, "IdleSitCrossLeggedEnter")
EndEvent

Event OnEffectFinish(Actor akTarget, Actor akCaster)
  pModRunningFatiguePlayerScript.StopFatigue()
  PlayerRef.PlayIdle(IdleSitCrossLeggedExit)
  Game.SetPlayerAIDriven(false)
  Game.EnablePlayerControls()
  Utility.Wait(0.5)
  Actor FollowerActor = pFollowerAliasScript.GetActorRef() as Actor
  Debug.SendAnimationEvent(FollowerActor, "IdleChairExitStart")
EndEvent

 

Edited by vn524135
Link to comment
Share on other sites

all I am gonna say is Yeah... your getting there mate... btw if you need to call the same function or fire the same event in a script  twice, but require a different result, that when you need a state, always keep that in mind, now the script is two different states 

Just asking, who is the caster or the target in the magic effect?

(Actor akTarget, Actor akCaster)

use the variables passed to you to  your advantage, I see no akTarget or akCaster in your code, let's chat about that, tell me who they are?

Link to comment
Share on other sites

Posted (edited)
2 hours ago, PeterMartyr said:

all I am gonna say is Yeah... your getting there mate... btw if you need to call the same function or fire the same event in a script  twice, but require a different result, that when you need a state, always keep that in mind, now the script is two different states 

Just asking, who is the caster or the target in the magic effect?

(Actor akTarget, Actor akCaster)

use the variables passed to you to  your advantage, I see no akTarget or akCaster in your code, let's chat about that, tell me who they are?

Unfortunately, I don't have much knowledge. According to wiki, akTarget is "the Actor this effect was applied to", and akCaster is "the Actor that cast the spell this effect was from.". Both can be the player or an NPC. I can use them in the code like this;

if akCaster == Game.GetPlayer()
endif

if akTarget == Game.GetPlayer()
endif

But I didn't see the need to use them because the player is the only actor with the magic.

Edit: The caster and the target is the player. Casts itself by pressing the Z key.

Edited by vn524135
Link to comment
Share on other sites

Posted (edited)
17 hours ago, PeterMartyr said:

you define who the are when you cast the spell, give me some time I will show an example

Then, as I understand it, if it is defined as akCaster = FollowerActor, the follower is considered the caster, even if the player or a non-follower NPC casts the spell.

20 hours ago, PeterMartyr said:

all I am gonna say is Yeah... your getting there mate... btw if you need to call the same function or fire the same event in a script  twice, but require a different result, that when you need a state, always keep that in mind, now the script is two different states 

Just asking, who is the caster or the target in the magic effect?

(Actor akTarget, Actor akCaster)

use the variables passed to you to  your advantage, I see no akTarget or akCaster in your code, let's chat about that, tell me who they are?

Following your information, I changed the script so there will not be unnecessary updates every five seconds when the player is fatigued and can't run. This is a big improvement, and I thank you very much for your help. Here is the current version of the script:

Spoiler
Scriptname modRunningFatiguePlayerScript extends ReferenceAlias  

Actor PlayerRef
Float currentCarryWeight
Int runningCounter

Function StartFatigue()
  currentCarryWeight = PlayerRef.GetActorValue("CarryWeight")
  PlayerRef.DamageActorValue("CarryWeight", currentCarryWeight)
  GotoState("Fatigued")
EndFunction

Function StopFatigue()
  PlayerRef.RestoreActorValue("CarryWeight", currentCarryWeight)
  runningCounter = 0
  GotoState("Counting")
EndFunction

Function StartWarningFatigue()
  currentCarryWeight = PlayerRef.GetActorValue("CarryWeight")
  PlayerRef.DamageActorValue("CarryWeight", currentCarryWeight)
  Utility.Wait(4)
  PlayerRef.RestoreActorValue("CarryWeight", currentCarryWeight)
EndFunction

Event OnInit()
  PlayerRef = Game.GetPlayer()
  runningCounter = 0
  GotoState("Counting")
  RegisterForSleep()
  RegisterForSingleUpdate(3.0)
EndEvent

State Counting
Event OnBeginState()
  RegisterForSingleUpdate(3.0)
EndEvent

Event OnUpdate()
  if PlayerRef.IsRunning() && !PlayerRef.IsInCombat() && !PlayerRef.IsSneaking()
    runningCounter+=5
  endif

  if runningCounter == 45
    runningCounter = 50
    StartWarningFatigue()
  endif
  
  if runningCounter >= 60
    if !PlayerRef.IsSprinting()
      StartFatigue()
    endif
  else 
    RegisterForSingleUpdate(5.0)    
  endif
EndEvent

Event OnSleepStop(bool abInterrupted)
  StopFatigue()
EndEvent
EndState

State Fatigued
Event OnBeginState()
  RegisterForSingleUpdate(180.0)
EndEvent

Event OnUpdate()
  StopFatigue()
EndEvent

Event OnSleepStop(bool abInterrupted)
  StopFatigue()
EndEvent
EndState

 

Edited by vn524135
Link to comment
Share on other sites

  • 2 weeks later...

For the sake of speed and efficiency, I'll only suggest you avoid using function wrappers like RestoreAV and instead of using Game.GetPlayer(), you have 2 faster options: 1. Use the Actor PlayerRef property, or 2: Use an Actor player variable and assign Game.GetPlayer() to it in OnInit so that it is called exactly once and then used throughout the script.

As you're using a complex update, speed is very important IMO. RestorAV/DamageAV etc just calls RestoreActorValue. It's more efficient to use RestoreActorValue, etc instead.

Link to comment
Share on other sites

On 6/26/2024 at 10:08 PM, Evangela said:

For the sake of speed and efficiency, I'll only suggest you avoid using function wrappers like RestoreAV and instead of using Game.GetPlayer(), you have 2 faster options: 1. Use the Actor PlayerRef property, or 2: Use an Actor player variable and assign Game.GetPlayer() to it in OnInit so that it is called exactly once and then used throughout the script.

As you're using a complex update, speed is very important IMO. RestorAV/DamageAV etc just calls RestoreActorValue. It's more efficient to use RestoreActorValue, etc instead.

I apologize for replying to your message late. I thought the forum notifications appeared in the non-forum notifications of the site. Many thanks for your message and this information. While working on the script, I learned these improvements when searching the forum and made the adjustments to the script. The final version of the script is in my last message. It would have been better to edit my first message and add the final version of the script to avoid confusions, I apologize for not doing that. Here is the final version of the script:

Spoiler
Scriptname modRunningFatiguePlayerScript extends ReferenceAlias  

Actor PlayerRef
Float currentCarryWeight
Int runningCounter

Function StartFatigue()
  currentCarryWeight = PlayerRef.GetActorValue("CarryWeight")
  PlayerRef.DamageActorValue("CarryWeight", currentCarryWeight)
  GotoState("Fatigued")
EndFunction

Function StopFatigue()
  PlayerRef.RestoreActorValue("CarryWeight", currentCarryWeight)
  runningCounter = 0
  GotoState("Counting")
EndFunction

Function StartWarningFatigue()
  currentCarryWeight = PlayerRef.GetActorValue("CarryWeight")
  PlayerRef.DamageActorValue("CarryWeight", currentCarryWeight)
  Utility.Wait(4)
  PlayerRef.RestoreActorValue("CarryWeight", currentCarryWeight)
EndFunction

Event OnInit()
  PlayerRef = Game.GetPlayer()
  runningCounter = 0
  GotoState("Counting")
  RegisterForSleep()
  RegisterForSingleUpdate(3.0)
EndEvent

State Counting
Event OnBeginState()
  RegisterForSingleUpdate(3.0)
EndEvent

Event OnUpdate()
  if PlayerRef.IsRunning() && !PlayerRef.IsInCombat() && !PlayerRef.IsSneaking()
    runningCounter+=5
  endif

  if runningCounter == 45
    runningCounter = 50
    StartWarningFatigue()
  endif
  
  if runningCounter >= 60
    if !PlayerRef.IsSprinting()
      StartFatigue()
    endif
  else 
    RegisterForSingleUpdate(5.0)    
  endif
EndEvent

Event OnSleepStop(bool abInterrupted)
  StopFatigue()
EndEvent
EndState

State Fatigued
Event OnBeginState()
  RegisterForSingleUpdate(180.0)
EndEvent

Event OnUpdate()
  StopFatigue()
EndEvent

Event OnSleepStop(bool abInterrupted)
  StopFatigue()
EndEvent
EndState

And I want to say that I published the mod here; https://www.nexusmods.com/skyrim/mods/118622 Thank you again!

Link to comment
Share on other sites

On 6/27/2024 at 4:38 AM, Evangela said:

For the sake of speed and efficiency, I'll only suggest you avoid using function wrappers like RestoreAV and instead of using Game.GetPlayer(), you have 2 faster options: 1. Use the Actor PlayerRef property, or 2: Use an Actor player variable and assign Game.GetPlayer() to it in OnInit so that it is called exactly once and then used throughout the script.

As you're using a complex update, speed is very important IMO. RestorAV/DamageAV etc just calls RestoreActorValue. It's more efficient to use RestoreActorValue, etc instead.

@Evangela dude the saving in a modern gaming rig  is what, 1 ten thousands of a second or less?  Pfft  you can run your bad code 10, 000 or more time in 1 second.... how is that a insignificant improvement ??? and guess what PC are getting faster too...

Edit in a shitty PC it still would be measured in milliseconds 

Edit#2 what your sayin had merit 15, 20, years ago.. I will admit that, when they started preaching it.. but  I think we have move on and it is no importance in this day and age, you need to let it go... 

Link to comment
Share on other sites

  • Recently Browsing   0 members

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