Jump to content

Using global variables as an "index" for a "state machine"


Recommended Posts

Good evening everybody!

 

A while ago I asked about using quests (quest stages) as a state machine.

Somebody told me that that isn't really possible because you can't decrement quest stages.

 

So I got told to use global variables instead.

Alright, but that brings up a very big question:

 

 

For quest stages, there is a nice "event" that lets you do something when a certain quest stage is reached (OnStageSet).

But there is no such thing for global variables.

 

So how would I "do something" (in a scirpt) when a global variable reaches a certian value?

Something like "OnStageSet" but for global variables.

 

 

If there is no such thing, how else should something like this be done?

And don't tell me that you can't implement a state machine in a game in the 21st century, because that would just be sad ...

Link to comment
Share on other sites

Don't use a global variable. Use a property on a quest. Make it a full property with getter and setter functions, so these are the only way the state variable can be altered. Then, on the setter property, raise a CustomEvent whenever someone changes the value. Anyone who needs to know can register for the event.

Link to comment
Share on other sites

Don't use a global variable. Use a property on a quest. Make it a full property with getter and setter functions, so these are the only way the state variable can be altered.

I am sorry for the "n00b" question, but how do I do that?

I haven't really been doing much with "functions" in scripts ...

Link to comment
Share on other sites

Don't use a global variable. Use a property on a quest. Make it a full property with getter and setter functions, so these are the only way the state variable can be altered. Then, on the setter property, raise a CustomEvent whenever someone changes the value. Anyone who needs to know can register for the event.

 

+1 Great idea.

Link to comment
Share on other sites

 

Don't use a global variable. Use a property on a quest. Make it a full property with getter and setter functions, so these are the only way the state variable can be altered.

I am sorry for the "n00b" question, but how do I do that?

I haven't really been doing much with "functions" in scripts ...

 

Like this:

scriptname statemachine  extends quest

int START_STATE = 0 const
int STEADY_STATE = 1 const
int END_STATE = 2 const

CustomEvent State_Changed

int state_variable = START_STATE

property StateVariable
        function get()
                return state_variable
        endfunction
        function set(int value)
;
;               transition checking
;
                if value == END_STATE
                        if state_variable != STEADY_STATE
                                return          ; in any other language we'd raise an exception
                        endif                   ; as it is, there's no way to communcate the error
                elsif value = STEADY_STATE
                        if state_variable != START_STATE
                                return
                        endif
                else
                        return  ; can't transition to start state, so anything else is an error
                endif
;
;               set the state
;
                int old_state = state_variable
                state_variable = value
;
;               raise the event
;
                var[] args = new var[2]
                args[0] = state_variable
                args[1] = state_variable
                SendCustomEvent("State_Changed", args)
        endfunction
endproperty

That's for a simple 3-state machine, where START_STATE can only transition to STEADY_STATE and STEADY_STATE can only go to END_STATE. You'll want something more sophisticated, and probably end up putting the state checking in one or more separate functions.

 

The property thing is the way all properties work "under the hood". Saying

int property foo auto

is just shorthand for

int _foo
int property foo
        int function get()
                return _foo
        endfunction
        function set(int value)
                _foo = value
        endfunction
endproperty

... but you can use the long form to add extra processing to getting and or setting the value.

Edited by DocClox
Link to comment
Share on other sites

  • 3 weeks later...

Ok, let's say I have a script that has the state machine in it.

And I I have an object that I want to enable if the state machine reaches a certain state.

I want to do that with a script attached to the "object that should be enabled".

 

How would I do that?

There doesn't seem to be an "OnStateSet" event ...

Link to comment
Share on other sites

I just thought of another option, if you're interested. To actually use States in the StateMachine script with RegisterForRemoteEvent OnBeginState in other scripts.

 

So your StateMachine script on the quest would look like this:

 

Scriptname statemachine extends Quest 

Event OnInit() 
    Utility.Wait(1)
    GoToState("StateA") 
EndEvent 

State StateA
    
EndState 

State StateB 
    
EndState
Then in your object reference script you can do this:
statemachine Property ScriptRef Auto 

Event OnInit()
    RegisterForRemoteEvent(ScriptRef, "OnBeginState")
EndEvent

Event ScriptObject.OnBeginState(ScriptObject akSender, string asOldState) 
    String CurrentState = akSender.GetState()
    If CurrentState == "StateA"
        ;do something 
    elseif CurrentState == "StateB"
        ;do something else 
    Endif 
EndEvent
to change states, in another script you can do this:
statemachine Property ScriptRef Auto 

Event SomeEvent()
    ScriptRef.GoToState("StateA")
EndEvent
Link to comment
Share on other sites

  • Recently Browsing   0 members

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