Jump to content

Understanding Papyrus States


Recommended Posts

Posted (edited)

Dear LL,

 

I'm trying to figure out states to prevent scripts from running in the background while dialogue is going on. I've used the Cipscis guide [1] for this code below. The idea is that the Player is rewarded or punished based on the amount of times the Follower is in the Player's crosshairs (to simulate paying attention in a slave/dom role). This then triggers a blocking dialogue using a global variable (mgtsFollowerNeed) to reward the Player based on various dialogue condition checks or a ForceGreet package/dialogue to punish them. The script is attached to a Player alias in a quest.

 

While the dialogue is occurring, the script should be in the "Busy" state. Is it okay to use a globalvariable like this to trigger the dialogue and switch between states or is there some better way? Is this the proper use of states? This script compiles fine, but I'm not sure if it is correct otherwise.

 

[1] http://www.cipscis.com/skyrim/tutorials/states.aspx


 

Scriptname mgtsLOSScript extends ReferenceAlias  

mgtsFunctionsScript Property mgtsFunctions Auto
Actor Property PlayerRef Auto
ReferenceAlias Property FollowerAlias Auto
ReferenceAlias Property LOSFailNPC Auto
GlobalVariable Property mgtsFollowerNeed Auto

Int CrosshairCount = 0
Int NotInCrossHairCount = 0

Event OnInit()
    If Self.GetOwningQuest().IsRunning()
        RegisterForSingleUpdate(1.0)
    EndIf
EndEvent

Function IncrementCrosshairCount()
    GoToState("Busy")
    Actor akFollower = FollowerAlias.GetActorRef()
    String FollowerName = akFollower.getLeveledActorbase().getName()
    
    If Game.GetCurrentCrosshairRef() == akFollower
        CrosshairCount = CrosshairCount + 1
        mgtsFunctions.TextOut("None","None","(mgtsLOSScript) "+FollowerName+" is in crosshair ["+CrosshairCount+"/"+NotInCrosshairCount+"].")
    Else
        NotInCrossHairCOunt = NotInCrossHairCOunt + 1
        mgtsFunctions.TextOut("None","None","(mgtsLOSScript) "+FollowerName+" is NOT in crosshair ["+CrosshairCount+"/"+NotInCrosshairCount+"].")
    EndIf
    GoToState("")
EndFunction

Function CheckConditions()

    Actor akFollower = FollowerAlias.GetActorRef()
    String FollowerName = akFollower.getLeveledActorbase().getName()
    
    If CrosshairCount >= 5 && CrosshairCount > NotInCrossHairCount && mgtsFollowerNeed.GetValue() == 0.0
        mgtsFunctions.TextOut("None","None","(mgtsLOSScript) "+FollowerName+" was more often in the crosshair ["+CrosshairCount+" vs. "+NotInCrosshairCount+"].")
        CrosshairCount = 0
        NotInCrossHairCount = 0
        mgtsFollowerNeed.SetValue(1) ; used to trigger Blocking dialogue in quest
        GotoState("Disabled")
    EndIf
    
    If LOSFailNPC.GetRef() == None && NotInCrossHairCount >= 5 && NotInCrossHairCount > CrosshairCount && mgtsFollowerNeed.GetValue() == 0.0
        mgtsFunctions.TextOut("None","None","(mgtsLOSScript) "+FollowerName+" was less often in the crosshair ["+CrosshairCount+" vs. "+NotInCrosshairCount+"].")
        CrosshairCount = 0
        NotInCrossHairCount = 0
        mgtsFollowerNeed.SetValue(1)
        ; Assign Follower to forcegreet package
        LOSFailNPC.ForceRefIfEmpty(akFollower)
        GotoState("Disabled")
    EndIf
EndFunction

Event OnUpdate()
    IncrementCrosshairCount()
    CheckConditions()
    RegisterForSingleUpdate(10.0)
EndEvent


State Disabled

    Event OnUpdate()
        If mgtsFollowerNeed.GetValue() == 0.0
            GoToState("")
        EndIf
        RegisterForSingleUpdate(60.0)
    EndEvent
    
    Event OnEndState()
        RegisterForSingleUpdate(60)
        mgtsFunctions.TextOut("None","None","(mgtsLOSScript) Disabled state ended.")
    EndEvent

    Function CheckConditions()
    EndFunction
    
    Function IncrementCrosshairCount()
    EndFunction
EndState

 

Edited by invisible_rodent
Posted

Some issues I see here:

  1. NotInCrossHairCOunt, variable name typo.

  2. The Busy state doesn't exist.

  3. There is no point in putting the script into a Busy state in IncrementCrosshairCount.

  4. Inconsistent variable naming. akFollower and FollowerName for instance signals to me that FollowerName is a global variable, and akFollower is local - but they're both local. mgtsFunctions is global, but looks local. Look up camel casing, and Microsoft's variable naming schemes if you want examples.

  5. mgtsFollowerNeed can be get and set with just Value, GetValue() and SetValue() are legacy functions.

    If mgtsFollowerNeed.Value == 0.0
  6. Consider making akFollower and FollowerName global or pass them as arguments to IncrementCrosshairCount and CheckConditions. Both functions use them, and both have to fetch them, and they're both called one after the other.
  7. Consider renaming or refactoring CheckConditions(). The name is misleading, as it does more than just check things. It's also messy.
  8. GetCurrentCrosshairRef() probably doesn't do what you think it does. It only detects things that are within activation range. You need to cast a spell with a projectile if you want to measure anything beyond that distance. One of the Papyrus extender mods may contain ray tracing functions, but I don't recall seeing any.
  9. The OnInit event might only be called once, the first time the script is used. It most likely won't matter here since this is attached to the player, but if the update loop stops, this is something to look into.
  10. What you're doing with the Disabled state is correct for essentially disabling this mod, but I don't think I'd personally bother with this setup. I'd consider using IsMenuOpen instead:
    Return UI.IsMenuOpen("Dialogue Menu")

     

Posted

Wow! Thank you Traison, for all of your comments, especially on proper code writing. I'm afraid the rest of my mod is just as messy and inefficient as this bit...

 

I originally tried the Line of Sight functions, but it returned True as long as the Player could potentially see the Follower anywhere in the same room, not just limited to the first person camera view. If the LOS could just follow the first person view that would be better than activation distance, but perhaps this makes things more difficult for the Player. The greater mod is a giantess/survival mod that makes the game more difficult in various ways based on Player scale. Anyway, let me implement these changes and see what happens. Very much appreciate your comments and pointers!

 

 

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

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