Jump to content

Stopping activation within a function


antstubell

Recommended Posts

So have a large script here...

 

ObjectReference Property FullKboard Auto
ObjectReference Property LitCandleLeft Auto
ObjectReference Property UnlitCandleLeft Auto
ObjectReference Property LitCandleRight Auto
ObjectReference Property UnlitCandleRight Auto
ObjectReference Property KboardMiss2keys Auto
ObjectReference Property KboardMissCkey Auto
ObjectReference Property KboardMissFkey Auto
ObjectReference Property SNDHere Auto
Actor Property PlayerRef Auto
Float Property delay1 Auto
Float Property Pause Auto
GlobalVariable Property KeysInstalled Auto
Message Property OrganGreet Auto
Message Property Miss2keys Auto
Message Property Miss1key Auto
MiscObject Property KeyC Auto
MiscObject Property KeyF Auto
Sound Property MySNDnoF Auto
Sound Property MySNDnoC Auto
Sound Property MySNDnoCF Auto
Sound Property MySNDcomplete Auto

; C key added set value to 1
; F key added set value to 2
; both keys added set value to 3 End

Auto State Waiting
Event OnActivate(ObjectReference akActionRef)
if akActionRef == PlayerREF

Int iButtonA = OrganGreet.Show() ; Shows first menu
If iButtonA == 1 && (Game.GetPlayer().GetItemCount(KeyF) > 0) && (Game.GetPlayer().GetItemCount(KeyC) > 0) && KeysInstalled.GetValue() < 3
GotoState("Activated"); prevents re-activation may not be needed here
; player has both keys and it is the first time playing
Game.GetPlayer().RemoveItem(KeyF, 1)
Game.GetPlayer().RemoveItem(KeyC, 1)
KboardMiss2keys.disable()
KboardMissFkey.disable()
KboardMissCkey.disable()
LitCandleLeft.enable()
LitCandleRight.enable()
UnlitCandleLeft.disable()
UnlitCandleRight.disable()
FullKboard.enable()
MySNDcomplete.play(SNDHere)
;Utility.wait(delay1)
Debug.Notification ("Complete Keyboard Script Ended")
Self.disable()
Utility.wait(0.2)
Self.delete()

elseIf iButtonA == 1 && (Game.GetPlayer().GetItemCount(KeyC) < 1) && (Game.GetPlayer().GetItemCount(KeyF) < 1) && KeysInstalled.GetValue() == 0
; play organ with 2 missing keys for the first time
MySNDnoCF.play(SNDHere)
Utility.wait(delay1)
Miss2keys.show()

elseIf iButtonA == 1 && KeysInstalled.GetValue() == 1 || iButtonA == 1 && KeysInstalled.GetValue() == 2
CorFPlaced()
; send to 1 key already placed function

elseIf iButtonA == 1 && (Game.GetPlayer().GetItemCount(KeyC) > 0)
CKey()
; send to CKey function

elseIf iButtonA == 1 && (Game.GetPlayer().GetItemCount(KeyF) > 0)
FKey()
; send to FKey function


ElseIf iButtonA == 0

EndIf
Endif
Endevent
EndState
;--------------------------------------------------------------------------------------
Function CKey()
Debug.Notification ("Beginning C Key Function")
Utility.wait(Pause)
; player has C key in inventory
Game.GetPlayer().RemoveItem(KeyC, 1)
KeysInstalled.setvalue(1)
KboardMissFkey.enable()
LitCandleLeft.enable()
UnlitCandleLeft.disable()
KboardMiss2keys.disable()
MySNDnoF.play(SNDHere)
Utility.wait(delay1)
Miss1key.show()
EndFunction

Function FKey()
Debug.Notification ("Beginning F Key Function")
Utility.wait(Pause)
; player has F key in inventory
Game.GetPlayer().RemoveItem(KeyF, 1)
KeysInstalled.setvalue(2)
KboardMissCkey.enable()
LitCandleRight.enable()
KboardMiss2keys.disable()
UnlitCandleRight.disable()
MySNDnoC.play(SNDHere)
Utility.wait(delay1)
Miss1key.show()
EndFunction

Function CorFPlaced()
Debug.Notification ("Beginning C or F Key Already Placed Function")
Utility.wait(Pause)
; player has already placed a key and is playing organ with other key in inventory, this will complete scale
If KeysInstalled.GetValue() == 1 && (Game.GetPlayer().GetItemCount(KeyF) > 0); C key installed F added
Game.GetPlayer().RemoveItem(KeyF, 1); F key removed from inventory to complete scale
KboardMiss2keys.disable()
KboardMissFkey.disable()
KboardMissCkey.disable()
LitCandleLeft.enable()
LitCandleRight.enable()
UnlitCandleLeft.disable()
UnlitCandleRight.disable()
FullKboard.enable()
MySNDcomplete.play(SNDHere)
KeysInstalled.setvalue(3)
Utility.wait(delay1)
Debug.Notification ("C was installed F was added. Now what?")
Self.disable()
Utility.wait(0.2)
Self.delete()
EndIf

If KeysInstalled.GetValue() == 2 && (Game.GetPlayer().GetItemCount(KeyC) > 0); F key installed C added
Game.GetPlayer().RemoveItem(KeyC, 1); C key removed from inventory to complete scale
KboardMiss2keys.disable()
KboardMissFkey.disable()
KboardMissCkey.disable()
LitCandleLeft.enable()
LitCandleRight.enable()
UnlitCandleLeft.disable()
UnlitCandleRight.disable()
FullKboard.enable()
MySNDcomplete.play(SNDHere)
KeysInstalled.setvalue(3)
Utility.wait(delay1)
Debug.Notification ("F was installed C was added. Now what?")
Self.disable()
Utility.wait(0.2)
Self.delete()
EndIf

; player has installed C key and does not have F key in inventory
If KeysInstalled.GetValue() == 1 && (Game.GetPlayer().GetItemCount(KeyF) < 1)
MySNDnoF.play(SNDHere)
Utility.wait(delay1)
Miss1key.show()
Endif
; player has installed F key and does not have C key in inventory
If KeysInstalled.GetValue() == 2 && (Game.GetPlayer().GetItemCount(KeyC) < 1)
MySNDnoC.play(SNDHere)
Utility.wait(delay1)
Miss1key.show()
Endif
EndFunction

 

… and issue is stopping it being re-activated once it has been activated.

Auto State Waiting is set before the event.

GotoState("Activated") is set after the first button prompt.

EndState is set after event is finished.

But in between all of this the script is sent to various functions. Within these functions the script can be re-activated, The functions have a Utility.wait(delay1) so as the sound file can finish playing.

Point is within functions how can I stop the script being re-activated?

Link to comment
Share on other sites

Doesn't help your issue, but you have a property for the player with the variable name PlayerREF. You use it to compare the akActionRef of the OnActivate event to ensure that it is the player activating. Yet from there you are using Game.GetPlayer(). You can speed up the script a bit by replacing all those Game.GetPlayer() calls with the PlayerREF variable or for those within the OnActivate event you can use akActionRef once you've determined that it is indeed the player.

 

As far as the issue...

I am wondering if moving the functions to a separate script would help any.

There is BlockActivation which may or may not work in your case.

You could try disabling the player's ability to activate objects with DisablePlayerControls. Just be sure to re-enable them afterwards.

Link to comment
Share on other sites

In this Script situation the - GotoState("Activated") - needs to be define, is not working the same way as in the script you pull it from, that script didn't need definition because it was an ( i'll name it ) fire and forget script.

Here you need to script it like this (i'll change GotoState("Activated") ), example:




Auto State Waiting
Event OnActivate(ObjectReference akActionRef)
if akActionRef == PlayerREF
GoToState("Busy") ; Will prevent any further activation when entering FUNCTIONS and you have left-exited the MENU

Int iButtonA = OrganGreet.Show() ; Shows first menu
If iButtonA == 1 ........

CorFPlaced() ; When entering This FUNCTION you have already LEFT-EXITED the MENU and the script " I " will still be in a state "BUSY"

else
; Something
Endif


If iButtonA == 2 ........

FKey() ; When entering This FUNCTION you have already LEFT-EXITED the MENU and the script " I " will still be in a state "BUSY"

else
; Something
Endif


Endif
; I have finish all my FUNCTIONS and i will go to a State that I CAN BE RE-ACTIVATED AGAIN
GoToState("Waiting")

Endevent
Endstate


State Busy
Event OnActivate(ObjectReference akActionRef)
;Do Nothing.
EndEvent
EndState


Function CorFPlaced()
; Do Your Stuff

; I am still in a "BUSY" State and you can't interact with me - "this activator" after you have exited the MENU

Endfunction


Function FKey()
; Do Your Stuff

; I am still in a "BUSY" State and you can't interact with me - "this activator" after you have exited the MENU

Endfunction




You can call different " STATES " in different "iButtons" with different "Functions" if all of those "STATES" are define and the " ENTER STATE - EXIT STATE " is properly called.

The more STATES and Functions , the more complex your script will become, and one simple bad call enter-exit state will F**** UP your whole script.


In this kind of script is better to have each iButton in their own "close" condition and not use " ElseIf ", for better - clearer script, easier to see when an "Action" is entering a "STATE" & "EXITING" & which "FUNCTIONS" is in which "STATE".


Edit: Typo...

Edited by maxarturo
Link to comment
Share on other sites

@IsharaMeradin-

I used PlayerRef because it is possible that an NPC can trigger the script.

When using...

if akActionRef == PlayerREF

How would, for example, this line of script need to/can be changed to, as you say, speed things up?

If iButtonA == 1 && (Game.GetPlayer().GetItemCount(KeyF) > 0) && (Game.GetPlayer().GetItemCount(KeyC) > 0) && KeysInstalled.GetValue() < 3

Link to comment
Share on other sites

Game.GetPlayer() calls out to the game script to obtain the player information from the GetPlayer function. This pauses the current thread until that is complete.

 

Since you have already a property with the player information contained within. You can use that to keep the current thread from being paused as it will not be going to the Game script to run the GetPlayer() function. This means that you can use PlayerREF anywhere in your script that you are using Game.GetPlayer().

 

If you did not have the PlayerREF property but instead did in the OnActivate event

If akActionRef == Game.GetPlayer()

You could then use akActionRef anywhere else within the OnActivate event underneath that condition check.

Example using your event from the first post

 

 

Event OnActivate(ObjectReference akActionRef)
  if akActionRef == Game.GetPlayer()
    Int iButtonA = OrganGreet.Show() ; Shows first menu
    If iButtonA == 1 && (akActionRef().GetItemCount(KeyF) > 0) && (akActionRef().GetItemCount(KeyC) > 0) && KeysInstalled.GetValue() < 3
      GotoState("Activated"); prevents re-activation may not be needed here
      ; player has both keys and it is the first time playing
      akActionRef().RemoveItem(KeyF, 1)
      akActionRef().RemoveItem(KeyC, 1)
      KboardMiss2keys.disable()
      KboardMissFkey.disable()
      KboardMissCkey.disable()
      LitCandleLeft.enable()
      LitCandleRight.enable()
      UnlitCandleLeft.disable()
      UnlitCandleRight.disable()
      FullKboard.enable()
      MySNDcomplete.play(SNDHere)
      ;Utility.wait(delay1)
      Debug.Notification ("Complete Keyboard Script Ended")
      Self.disable()
      Utility.wait(0.2)
      Self.delete()

    elseIf iButtonA == 1 && (akActionRef().GetItemCount(KeyC) < 1) && (akActionRef().GetItemCount(KeyF) < 1) && KeysInstalled.GetValue() == 0
      ; play organ with 2 missing keys for the first time
      MySNDnoCF.play(SNDHere)
      Utility.wait(delay1)
      Miss2keys.show()

    elseIf iButtonA == 1 && KeysInstalled.GetValue() == 1 || iButtonA == 1 && KeysInstalled.GetValue() == 2
      CorFPlaced()
      ; send to 1 key already placed function

    elseIf iButtonA == 1 && (akActionRef().GetItemCount(KeyC) > 0)
      CKey()
      ; send to CKey function

    elseIf iButtonA == 1 && (akActionRef().GetItemCount(KeyF) > 0)
      FKey()
      ; send to FKey function


    ElseIf iButtonA == 0

    EndIf
  Endif
Endevent

 

Basically, once you know that a parameter of an event or function contains the data you seek, you can use that variable instead within that event or function.

 

Hopefully that helps. There are threads out there that discuss this as well as the pros and cons of using a local variable vs property to store the player data. I do not wish to get into all that right now. If that interests you feel free to search them out.

Link to comment
Share on other sites

You wrote: "I used PlayerRef because it is possible that an NPC can trigger the script."

Well.. NPC may able to actvate, but there is no reason for using of playerRef here.

 

Keep in mind that conditions should not contain redundant code, which makes runtime often slower and for you its much harder to maintain the source code.

Maybe next is working for you, have a look for "gotoState()":

 

antActivationScript

 

Scriptname antActivationScript extends ObjectReference

; https://forums.nexusmods.com/index.php?/topic/8003908-stopping-activation-within-a-function/

  GlobalVariable PROPERTY KeysInstalled auto        ; [default getvalue() == Zero]
    ; C key added set value to 1
    ; F key added set value to 2
    ; both keys added set value to 3 End

  Message PROPERTY OrganGreet auto
  Message PROPERTY Miss1key   auto
  Message PROPERTY Miss2keys  auto

  MiscObject PROPERTY KeyC auto
  MiscObject PROPERTY KeyF auto

  Sound PROPERTY MySNDnoF  auto
  Sound PROPERTY MySNDnoC  auto
  Sound PROPERTY MySNDnoCF auto
  Sound PROPERTY MySNDcomplete auto

  ObjectReference PROPERTY LitCandleLeft    auto
  ObjectReference PROPERTY LitCandleRight   auto
  ObjectReference PROPERTY UnlitCandleLeft  auto
  ObjectReference PROPERTY UnlitCandleRight auto

  ObjectReference PROPERTY SNDHere          auto
  ObjectReference PROPERTY FullKboard       auto
  ObjectReference PROPERTY KboardMiss2keys  auto
  ObjectReference PROPERTY KboardMissCkey   auto
  ObjectReference PROPERTY KboardMissFkey   auto

 ;Actor Property PlayerRef Auto

  Float PROPERTY delay1 auto
  Float PROPERTY Pause  auto


; -- EVENTs --

EVENT OnActivate(ObjectReference akActionRef)
IF (akActionRef == Game.GetPlayer() as ObjectReference)
ELSE
    RETURN    ; - STOP -    not player activated, do nothing
ENDIF
;---------------------
    IF (OrganGreet.Show() == 1)             ; menu for player choice (yes/no)
        myF_Choice(akActionRef as Actor)
    ENDIF
ENDEVENT


;===================================
State Done    ; do not track activation here
;=========
EVENT OnActivate(ObjectReference akActionRef)
ENDEVENT
;=======
endState


; -- FUNCTIONs -- 6

;--------------------------------
FUNCTION myF_Choice(Actor player)  ; internal
;--------------------------------
    gotoState("Done")                ; ### STATE ###  prevents re-activation during wait
    float f = KeysInstalled.GetValue()

IF (f >= 3)
    RETURN    ; - STOP -    saftey first, both keys are already installed
ENDIF
;---------------------
    IF (f == 1) || (f == 2)
        myF_OtherKey(player, f)                ; send to 1 key already placed function

    ELSEIF (player.GetItemCount(KeyC) > 0)
        IF (player.GetItemCount(KeyF) > 0)
            myF_Ready(player)
        ELSE
            myF_Key1(player)                ; send to CKey function
            gotoState("")            ; ### STATE ###
        ENDIF
    
    ELSEIF (player.GetItemCount(KeyF) > 0)
;;;        IF (player.GetItemCount(KeyC) > 0)        ; redundant condition !!
;;;            myF_Ready(player)
;;;        ELSE
            myF_Key2(player)                ; send to FKey function
            gotoState("")            ; ### STATE ###
;;;        ENDIF

    ELSE
        MySNDnoCF.Play(SNDHere)             ; play organ with 2 missing keys
        Utility.Wait(delay1)
        Miss2keys.Show()
        gotoState("")                ; ### STATE ###
    ENDIF
ENDFUNCTION


;-------------------------------------------
FUNCTION myF_OtherKey(Actor player, Float f)  ; internal helper
;-------------------------------------------
    Debug.Notification ("Beginning C or F Key Already Placed Function")
    Utility.Wait(Pause)

; player has already placed a key and is playing organ with other key in inventory, this will complete scale
    int i = 0

    IF (f == 1)
        IF (player.GetItemCount(KeyF) > 0)        ; C key installed F added
            player.RemoveItem(KeyF, 1)            ; F key removed from inventory to complete scale
            KeysInstalled.SetValue(3)
            i = 1
        ELSE                                ; player has installed C key and does not have F key in inventory
            MySNDnoF.Play(SNDHere)
        ENDIF

    ELSE ;IF (f == 2)
        IF (player.GetItemCount(KeyC) > 0)        ; F key installed C added
            player.RemoveItem(KeyC, 1)            ; C key removed from inventory to complete scale
            KeysInstalled.SetValue(3)
            i = 2
        ELSE                                ; player has installed F key and does not have C key in inventory
            MySNDnoC.Play(SNDHere)
        ENDIF
    ENDIF
;    -----------
    IF (i == 0)
        Utility.Wait(delay1)
        Miss1key.Show()
        gotoState("")                ; ### STATE ###
    ELSE
        myF_Delete(i)    ; ***
    ENDIF
ENDFUNCTION


;-------------------------------
FUNCTION myF_Ready(Actor player)  ; internal helper
;-------------------------------
; player has both keys and it is the first time playing
    player.RemoveItem(KeyF, 1)
    player.RemoveItem(KeyC, 1)
    KeysInstalled.SetValue(3)

    myF_Delete(0)        ; ***
ENDFUNCTION


;-------------------------
FUNCTION myF_Delete(Int i)  ; internal helper
;-------------------------
    KboardMiss2keys.DisableNoWait()
    KboardMissFkey.DisableNoWait()
    KboardMissCkey.DisableNoWait()

    UnlitCandleLeft.DisableNoWait()
    LitCandleLeft.Enable()

    UnlitCandleRight.DisableNoWait()
    LitCandleRight.Enable()

    FullKboard.Enable()
    MySNDcomplete.Play(SNDHere)
    ;Utility.Wait(delay1)
        
;;;    IF     (i == 1)
;;;        Debug.Notification ("C was installed F was added. Now what?")
;;;    ELSEIF (i == 2)
;;;        Debug.Notification ("F was installed C was added. Now what?")
;;;    ELSE
        Debug.Notification ("Complete Keyboard Script Ended")
;;;    ENDIF

    self.DisableNoWait()
    Utility.Wait(0.25)
    self.Delete()        ; mark this object as deleted, wait for ending of this script and any object related persistence in other scripts
ENDFUNCTION


;------------------------------
FUNCTION myF_Key1(Actor player)  ; internal helper
;------------------------------
    Debug.Notification ("Beginning C Key Function")
    Utility.Wait(Pause)

; player has C key in inventory
    player.RemoveItem(KeyC as Form, 1)
    KeysInstalled.SetValue(1)

    KboardMiss2keys.DisableNoWait()
    KboardMissFkey.Enable()

    UnlitCandleLeft.DisableNoWait()
    LitCandleLeft.Enable()

    MySNDnoF.Play(SNDHere)
    Utility.Wait(delay1)

    Miss1key.Show()
ENDFUNCTION


;------------------------------
FUNCTION myF_Key2(Actor player)  ; internal helper
;------------------------------
    Debug.Notification ("Beginning F Key Function")
    Utility.Wait(Pause)

; player has F key in inventory
    player.RemoveItem(KeyF as Form, 1)
    KeysInstalled.SetValue(2)

    KboardMiss2keys.DisableNoWait()
    KboardMissCkey.Enable()

    UnlitCandleRight.DisableNoWait()
    LitCandleRight.Enable()

    MySNDnoC.Play(SNDHere)
    Utility.Wait(delay1)

    Miss1key.Show()
ENDFUNCTION

 

 

 

You asked: "Point is within functions how can I stop the script being re-activated?"

gotoState("Done")

Let the script in this state and whenever the player is trying to activate, the script will do nothings.

Edited by ReDragon2013
Link to comment
Share on other sites

Problem I don't get.

This compiles and works, as in the 'old way.'

 

Actor Property PlayerREF Auto
ObjectReference Property PlayerMoveTargetREF Auto
ObjectReference Property Primi1 Auto

Event OnActivate(ObjectReference akActionRef)
if akActionRef == Game.GetPlayer()

Game.GetPlayer().MoveTo(PlayerMoveTargetREF)
Primi1.disable(); disable the trigger box that teleported player here

EndIf
EndEvent

 

This won't compile.

 

Actor Property PlayerREF Auto
ObjectReference Property PlayerMoveTargetREF Auto
ObjectReference Property Primi1 Auto

Event OnActivate(ObjectReference akActionRef)
if akActionRef == Game.GetPlayer()

akActionRef().MoveTo(PlayerMoveTargetREF)
Primi1.disable(); disable the trigger box that teleported player here

EndIf
EndEvent

 

Errors;

(10,0): akActionRef is not a function or does not exist

10,14): none is not a known user-defined type

Link to comment
Share on other sites

  • Recently Browsing   0 members

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