Jump to content

NPC starts a fire. No magic involved. Ideally no traps either. Help.


antstubell

Recommended Posts

Dumb question from an onlooker, but isn't GoToState("AllDone") supposed to be _after_ the script does stuff?

 

diziet

No. The processing thread has to complete that block before it can be released. Despite the script being told to go to a state that does not allow anything to happen when the event gets triggered, the current processing of that code block still gets executed. The state merely prevents any additional event triggers from processing the code.

Link to comment
Share on other sites

Hi antstubell

Sorry for my late response, but i've been so busy with work.

Although i have done this, i do admitte that i've never use this logic with 'Light' objects.


This needs some testing, but i think using "GetBaseObject()' as dylbill did is the key.



@ dizietemblesssma

As IsharaMeradin already explain, the "OnTrigger" event will fire multiple times once the object is inside, in contrast with the "OnTriggerEnter/Leave" which will fire only one.


In my humble opinion "States" are the most powerful tool that papyrus has, they can serve as 'fail safes' when they are called in an 'empty state' to prevent a reactivation from firing, this is the most common use of states.


But aside from that, they have sooooo Many Applications !, you can even make the same script run another function while the initial script function is "Paused", or have different versions of the script inside the same script. And many, many more....


The tricky part with 'States' is that they need a carefully pre constructed script idea before actually writing it, the more complicated the use of 'States' becomes, the easiest is to lose track of 'what does what' and what 'State' is f***** up your whole script, since only one wrong 'State' call will result in chaos.


Plus, the biggest drawback with states is that mistakes been made will not trigger a "Compiler Error", and this is a big trap, because your script could be fully functional, but is not working because you have a "TYPO" on a state !!!, or a wrong state call.


Have all a nice weekend.

Edited by maxarturo
Link to comment
Share on other sites

Most state usage is done to block something from happening again. A bool or some other variable could be used to block the inside code from running, but the event would still be triggered and take up some processing time to determine that it isn't supposed to do anything. A state containing the same event but without any code shortens the processing time considerably.

 

Consider the following example:

 

 

 

Event OnActivate(ObjectReference akActivator)
  Debug.Notification("You pressed a button!)
EndEvent

This will run every time the object is activated

 

Event OnActivate(ObjectReference akActivator)
  GoToState("DoNothing")
  Debug.Notification("You pressed a button!)
EndEvent
 
State DoNothing
  Event OnActivate(ObjectReference akActivator)
  EndEvent
EndState

This will display the text on the first activation and then never display it again.

 

 

 

Other times states are used to do something different for the same event. A typical situation is one where interaction with an object triggers a bunch of behind the scenes work (perhaps scanning player inventory for items to put on display). Switching states prior to starting the scan lets the author display a busy message to the player should they try to use the object again prior to completing the initial scan.

Link to comment
Share on other sites

What's the difference when a state ("IsInBrackets") like that and not.

What are the states doing in this short script and why do they have different names - busy, done, waiting?

 

auto state waiting

Event OnTriggerEnter(ObjectReference akActionRef)
if akActionRef == PlayerRef
GotoState("Busy")

xMarkerSpell.placeAtMe(MyMagFX)
xMarkerSpell.placeAtMe(MyFX)
xMarkerSpell.placeAtMe(myFXShader)
Utility.Wait(Delay)
EnObj1.Enable()
MySND.Play(SNDHere)

GoToState("Done")

EndIf
ENDEVENT
ENDSTATE

 

Edited by antstubell
Link to comment
Share on other sites

In short, if you have two or more states in your script, the only events that will run are the events in the state that the script is currently in. So if you did this:

 

auto state waiting ;the state the script is in when first initialized

    Event OnTriggerEnter(ObjectReference akActionRef)
        if akActionRef == PlayerRef
            GotoState("Busy")

            xMarkerSpell.placeAtMe(MyMagFX)
            xMarkerSpell.placeAtMe(MyFX)
            xMarkerSpell.placeAtMe(myFXShader)
            Utility.Wait(Delay)
            EnObj1.Enable()
            MySND.Play(SNDHere)

            GoToState("Done")

        EndIf
    EndEvent
EndState

State Busy
    Event OnTriggerEnter(ObjectReference akActionRef)
        Debug.Notification("Busy")
    EndEvent 
EndState 

State Done 
EndState

The script starts in the waiting state. When the player enters the trigger box, it goes to the busy state while processing the rest of the code. If something enters the trigger box while it's still processing, you'll get the "Busy" notification and the code in the Waiting state won't run again. Once it's done processing and goes to the Done state, then the events and code won't run at all anymore.

Link to comment
Share on other sites

What's the difference when a state ("IsInBrackets") like that and not.

 

The default state for a script is called the empty state. Every function or event not inside a specified state is considered to be inside the empty state. Calling GoToState("") tells the script to go to the empty state. Properties are always defined in the empty state even if used inside of other states.

 

Declaring a state is as simple as the following:

State NameOfState

EndState

 

NameOfState will be recognized by papyrus automatically as the state's name string and will go to that state when GoToState("NameOfState") is used.

 

This page may give you some further insight into states: https://www.creationkit.com/index.php?title=States_(Papyrus)

Link to comment
Share on other sites

I think I'm getting it. A state prevents other stuff from happening while a script is processing code. If I changed the last state GoToState ("Done") in the above script to GoToState ("Waiting") would this then set up the trigger box to be fired again?

 

BTW the script that was posted by dylbill repeatedly fires. The debug message reappears on screen all the time. Could I just Self.Disable() or Self.Delete() the script/trigger box to stop this?

 

EDIT: And the oil trap doesn't self activate.

Edited by antstubell
Link to comment
Share on other sites

Yes, that would set up the trigger box to be fired again. Looking at some vanilla scripts, it looks like you have to put the events with nothing in them to block them. Also I looked at the TrapOilPool vanilla script, and there's no OnActivate event, so instead in the script try this:

 

Light Property MyTorch Auto
ObjectReference Property MyOilPool Auto
Bool Check = False

EVENT OnTrigger(ObjectReference akActionRef)
    If Check == False
        Form Base = akActionRef.GetBaseObject()
        
        If Base as Light 
            If Base == MyTorch
                Check = True
                GoToState("AllDone")
                TrapOilPool OilPoolScript = MyOilPool as TrapOilPool
                OilPoolScript.gasExplode(Self)
                debug.notification("Whoosh!")
                
                ; Or whatever else you intend on doing to start the fire
            Endif
        EndIf
    Endif
ENDEVENT

STATE AllDone
    Event OnTrigger(ObjectReference akActionRef)
    Endevent
ENDSTATE

I also put a bool in to be doubly sure it only fires once.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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