antstubell Posted September 21, 2019 Share Posted September 21, 2019 So have a large script here... ObjectReference Property FullKboard AutoObjectReference Property LitCandleLeft AutoObjectReference Property UnlitCandleLeft AutoObjectReference Property LitCandleRight AutoObjectReference Property UnlitCandleRight AutoObjectReference Property KboardMiss2keys AutoObjectReference Property KboardMissCkey AutoObjectReference Property KboardMissFkey AutoObjectReference Property SNDHere AutoActor Property PlayerRef AutoFloat Property delay1 AutoFloat Property Pause AutoGlobalVariable Property KeysInstalled AutoMessage Property OrganGreet AutoMessage Property Miss2keys AutoMessage Property Miss1key AutoMiscObject Property KeyC AutoMiscObject Property KeyF AutoSound Property MySNDnoF AutoSound Property MySNDnoC AutoSound Property MySNDnoCF AutoSound Property MySNDcomplete Auto; C key added set value to 1; F key added set value to 2; both keys added set value to 3 EndAuto State WaitingEvent OnActivate(ObjectReference akActionRef)if akActionRef == PlayerREFInt iButtonA = OrganGreet.Show() ; Shows first menuIf iButtonA == 1 && (Game.GetPlayer().GetItemCount(KeyF) > 0) && (Game.GetPlayer().GetItemCount(KeyC) > 0) && KeysInstalled.GetValue() < 3GotoState("Activated"); prevents re-activation may not be needed here; player has both keys and it is the first time playingGame.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 timeMySNDnoCF.play(SNDHere)Utility.wait(delay1)Miss2keys.show()elseIf iButtonA == 1 && KeysInstalled.GetValue() == 1 || iButtonA == 1 && KeysInstalled.GetValue() == 2CorFPlaced(); send to 1 key already placed functionelseIf iButtonA == 1 && (Game.GetPlayer().GetItemCount(KeyC) > 0)CKey(); send to CKey functionelseIf iButtonA == 1 && (Game.GetPlayer().GetItemCount(KeyF) > 0)FKey(); send to FKey functionElseIf iButtonA == 0EndIfEndifEndeventEndState;--------------------------------------------------------------------------------------Function CKey()Debug.Notification ("Beginning C Key Function")Utility.wait(Pause); player has C key in inventoryGame.GetPlayer().RemoveItem(KeyC, 1)KeysInstalled.setvalue(1)KboardMissFkey.enable()LitCandleLeft.enable()UnlitCandleLeft.disable()KboardMiss2keys.disable()MySNDnoF.play(SNDHere)Utility.wait(delay1)Miss1key.show()EndFunctionFunction FKey()Debug.Notification ("Beginning F Key Function")Utility.wait(Pause); player has F key in inventoryGame.GetPlayer().RemoveItem(KeyF, 1)KeysInstalled.setvalue(2)KboardMissCkey.enable()LitCandleRight.enable()KboardMiss2keys.disable()UnlitCandleRight.disable()MySNDnoC.play(SNDHere)Utility.wait(delay1)Miss1key.show()EndFunctionFunction 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 scaleIf KeysInstalled.GetValue() == 1 && (Game.GetPlayer().GetItemCount(KeyF) > 0); C key installed F addedGame.GetPlayer().RemoveItem(KeyF, 1); F key removed from inventory to complete scaleKboardMiss2keys.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()EndIfIf KeysInstalled.GetValue() == 2 && (Game.GetPlayer().GetItemCount(KeyC) > 0); F key installed C addedGame.GetPlayer().RemoveItem(KeyC, 1); C key removed from inventory to complete scaleKboardMiss2keys.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 inventoryIf 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 inventoryIf KeysInstalled.GetValue() == 2 && (Game.GetPlayer().GetItemCount(KeyC) < 1)MySNDnoC.play(SNDHere)Utility.wait(delay1)Miss1key.show()EndifEndFunction … 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 More sharing options...
IsharaMeradin Posted September 21, 2019 Share Posted September 21, 2019 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 More sharing options...
maxarturo Posted September 22, 2019 Share Posted September 22, 2019 (edited) 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 September 22, 2019 by maxarturo Link to comment Share on other sites More sharing options...
antstubell Posted September 22, 2019 Author Share Posted September 22, 2019 @IsharaMeradin-I used PlayerRef because it is possible that an NPC can trigger the script.When using...if akActionRef == PlayerREFHow 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 More sharing options...
IsharaMeradin Posted September 22, 2019 Share Posted September 22, 2019 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 eventIf 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 More sharing options...
ReDragon2013 Posted September 22, 2019 Share Posted September 22, 2019 (edited) 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 September 22, 2019 by ReDragon2013 Link to comment Share on other sites More sharing options...
antstubell Posted September 23, 2019 Author Share Posted September 23, 2019 Thank you both. Very interesting stuff. Although I have no plans to go back and redo all my scripts, would take a long time, in future I will bear this advice in mind. Link to comment Share on other sites More sharing options...
antstubell Posted September 23, 2019 Author Share Posted September 23, 2019 Problem I don't get.This compiles and works, as in the 'old way.' Actor Property PlayerREF AutoObjectReference Property PlayerMoveTargetREF AutoObjectReference Property Primi1 AutoEvent OnActivate(ObjectReference akActionRef)if akActionRef == Game.GetPlayer()Game.GetPlayer().MoveTo(PlayerMoveTargetREF)Primi1.disable(); disable the trigger box that teleported player hereEndIfEndEvent This won't compile. Actor Property PlayerREF AutoObjectReference Property PlayerMoveTargetREF AutoObjectReference Property Primi1 AutoEvent OnActivate(ObjectReference akActionRef)if akActionRef == Game.GetPlayer()akActionRef().MoveTo(PlayerMoveTargetREF)Primi1.disable(); disable the trigger box that teleported player hereEndIfEndEvent Errors;(10,0): akActionRef is not a function or does not exist10,14): none is not a known user-defined type Link to comment Share on other sites More sharing options...
maxarturo Posted September 23, 2019 Share Posted September 23, 2019 (edited) Remove bracketsakActionRef.MoveTo(PlayerMoveTargetREF) This won't compile : akActionRef() Edited September 23, 2019 by maxarturo Link to comment Share on other sites More sharing options...
antstubell Posted September 23, 2019 Author Share Posted September 23, 2019 :wallbash: Link to comment Share on other sites More sharing options...
Recommended Posts