morrowind1979 Posted November 14, 2012 Share Posted November 14, 2012 Scriptname DagUrWelcome extends ObjectReference Sound Property DagothUrWelcomeSpeech Auto Event OnTriggerEnter(ObjectReference akActionRef)DagothUrWelcomeSpeech.Play(self) EndEvent Ok this is a script I created for a trigger box in my quest. the trigger activates every time the player enters teh trigger box. I only want the trigger to run once then disable teh trigger box how would i do this??? Link to comment Share on other sites More sharing options...
IsharaMeradin Posted November 14, 2012 Share Posted November 14, 2012 (edited) add a variable that is only true at the first instance i.e.Scriptname DagUrWelcome extends ObjectReference Sound Property DagothUrWelcomeSpeech Auto Int Property RunOnceVar = 0 Auto Event OnTriggerEnter(ObjectReference akActionRef) If RunOnceVar == 0 DagothUrWelcomeSpeech.Play(self) RunOnceVar = 1 EndIf EndEvent If that variable doesn't stick, then use a global variable instead EDIT: The above prevents the trigger from running again, but doesn't disable it. To completely disable the trigger you'll need to add an xmarker, make the xmarker an enable parent of the trigger box, then in your script after the sound plays have the script disable the xmarker and it will cause the trigger to disable. you may have to play with timing etc... so it would be more likeScriptname DagUrWelcome extends ObjectReference Sound Property DagothUrWelcomeSpeech Auto ObjectReference Property EnableMarker Auto {assign the xmarker to this property} Event OnTriggerEnter(ObjectReference akActionRef) DagothUrWelcomeSpeech.Play(self) Utility.Wait(5) EnableMarker.Disable() EndEvent either way may work for your purposes... Edited November 14, 2012 by IsharaMeradin Link to comment Share on other sites More sharing options...
morrowind1979 Posted November 14, 2012 Author Share Posted November 14, 2012 (edited) add a variable that is only true at the first instance i.e.Scriptname DagUrWelcome extends ObjectReference Sound Property DagothUrWelcomeSpeech Auto Int Property RunOnceVar = 0 Auto Event OnTriggerEnter(ObjectReference akActionRef) If RunOnceVar == 0 DagothUrWelcomeSpeech.Play(self) RunOnceVar = 1 EndIf EndEvent If that variable doesn't stick, then use a global variable instead EDIT: The above prevents the trigger from running again, but doesn't disable it. To completely disable the trigger you'll need to add an xmarker, make the xmarker an enable parent of the trigger box, then in your script after the sound plays have the script disable the xmarker and it will cause the trigger to disable. you may have to play with timing etc... so it would be more likeScriptname DagUrWelcome extends ObjectReference Sound Property DagothUrWelcomeSpeech Auto ObjectReference Property EnableMarker Auto {assign the xmarker to this property} Event OnTriggerEnter(ObjectReference akActionRef) DagothUrWelcomeSpeech.Play(self) Utility.Wait(5) EnableMarker.Disable() EndEvent either way may work for your purposes... Thanks what value do i put Runonce to in properties??? Nevermind just set it to 0 as default going to test ingame seems to have done teh trick thanks a lot!!! Edited November 14, 2012 by morrowind1979 Link to comment Share on other sites More sharing options...
IsharaMeradin Posted November 14, 2012 Share Posted November 14, 2012 You may want to test that across multiple saves. To make sure that it doesn't get triggered again in a new game session. If it does get triggered again, then you'll need to use a global variable (those are stored in the saves) or use the 2nd method I mentioned earlier. Link to comment Share on other sites More sharing options...
steve40 Posted November 16, 2012 Share Posted November 16, 2012 (edited) ^^ why so complicated? If the script is put on the trigger, then all you need to do is call disable() (on self) No need for markers at all. Also, as I mentioned in another topic, why use a property when a simple variable will suffice? In this case a boolean variable. And yes, it will save across savegames, no need for global variables. But if the object/script is disabled, then it is redundant anyway Another important point is that you probably want to test that it was the Player that entered the trigger, otherwise a stray NPC might mess things up... Also, you may want to use PlayAndWait in this case: Scriptname DagUrWelcome extends ObjectReference Sound Property DagothUrWelcomeSpeech Auto bool RunOnce Event OnTriggerEnter(ObjectReference ActionRef) If !RunOnce && ActionRef == Game.GetPlayer() RunOnce = true DagothUrWelcomeSpeech.PlayAndWait(self) disable() EndIf EndEvent Alternatively you could use States, but not really necessary: Scriptname DagUrWelcome extends ObjectReference Sound Property DagothUrWelcomeSpeech Auto AUTO STATE WAITING Event OnTriggerEnter(ObjectReference ActionRef) If ActionRef == Game.GetPlayer() GotoState("DONE") DagothUrWelcomeSpeech.PlayAndWait(self) disable() ; this is now optional, as the "DONE" state will render the script inactive anyway EndIf EndEvent END STATE STATE DONE END STATE Edited November 16, 2012 by steve40 Link to comment Share on other sites More sharing options...
Ez0n3 Posted November 16, 2012 Share Posted November 16, 2012 (edited) I prefer the sates method because I think it the fastest and has the least amount of overhead during and after the script has run. Same thing from slowest with most overhead to fastest with least overhead: Sound Property DagothUrWelcomeSpeech Auto bool RunOnce Event OnTriggerEnter(ObjectReference akActionRef) If (!RunOnce && akActionRef == Game.GetPlayer()) ; full blown check every trigger RunOnce = true DagothUrWelcomeSpeech.PlayAndWait(Self) Disable() EndIf EndEvent(same speed as above:)Sound Property DagothUrWelcomeSpeech Auto bool RunOnce Event OnTriggerEnter(ObjectReference akActionRef) If (RunOnce) ; light check every trigger Else If (akActionRef == Game.GetPlayer()) ; med check until player trigger RunOnce = true DagothUrWelcomeSpeech.PlayAndWait(Self) Disable() EndIf EndEventSound Property DagothUrWelcomeSpeech Auto Auto State Waiting Event OnTriggerEnter(ObjectReference akActionRef) If (akActionRef == Game.GetPlayer()) ; med check until player trigger GoToState("Done"); DagothUrWelcomeSpeech.PlayAndWait(Self) Disable() EndIf EndEvent EndState State Done EndStateThrow in the player ref instead of Game.GetPlayer(), and it is blazing :)Sound Property DagothUrWelcomeSpeech Auto Actor Property PlayerRef Auto ; edit, should be Actor, not ObjectReference Auto State Waiting Event OnTriggerEnter(ObjectReference akActionRef) If (akActionRef == PlayerRef) ; light check until player trigger GoToState("Done"); DagothUrWelcomeSpeech.PlayAndWait(Self) Disable() EndIf EndEvent EndState State Done EndStateIf you factor in speed and overhead, states take it imo. Edited November 16, 2012 by Ez0n3 Link to comment Share on other sites More sharing options...
steve40 Posted November 16, 2012 Share Posted November 16, 2012 (edited) @EzOn3: usually when IF statements are evaluated, as soon as part of an AND expression condition is false, the rest of the expression gets ignored because the whole condition will be false anyway. That's how I understand such statements are typically evaluated in programming languages in general. So I don't think there would be any notable performance gain in the second script (relative to the first one), unless Papyrus goes against the grain for some reason. But anyway, I agree that States are generally better, and they have the advantage of shutting off event blocks in the above examples. Edited November 16, 2012 by steve40 Link to comment Share on other sites More sharing options...
Ez0n3 Posted November 16, 2012 Share Posted November 16, 2012 (edited) I was under the impression that "&&" (and) has to check both even if the first doesn't qualify. I don't think "||" (or) suffers from that though. I have to double check, but that's how it works the last time I checked. Been wrong many times before though ;) Edit:I think I was thinking of FO3. I just noticed on the wiki:The AND operator (&&) will be true if both of the expressions to its left and right are true, and will short-circuit if the left expression is false (it will not evaluate the right expression at all).So ya, you're correct. One of the many improvements I'm still catching on to :) Should be no difference between the 1st and 2nd. Edited November 16, 2012 by Ez0n3 Link to comment Share on other sites More sharing options...
IsharaMeradin Posted November 16, 2012 Share Posted November 16, 2012 ^^ why so complicated?Complicated? sometimes the "easy" way is more complicated because that requires having actual programing knowledge. For someone like me who has to self teach themselves in the stuff that they use, complicated can be the easy way because when something does work you tend to stick with that. My scripting background comes from Baldur's Gate series where the game scripts were a series of IF THEN blocks evaluated from the top down. It makes it easier for me to see what is going on if I use IF statements. As long as the script functions, whether or not parts of it are unnecessary, I'm happy. Link to comment Share on other sites More sharing options...
acidzebra Posted November 16, 2012 Share Posted November 16, 2012 (edited) As long as the script functions, whether or not parts of it are unnecessary, I'm happy. I'll respectfully disagree - when we face a public running tens or hundreds of mods with any number of scripts, we should optimize our code as much as possible to reduce load on people's games. This helps both users and fellow modders. I do agree that with this whole "self-taught" thing (and who isn't when it comes to Papyrus?) it's easy to fall back to the "this works so okay" mode - but if you have the capacity to learn a new and better way, that same self-taught skill should update itself and learn a new and better trick :) I'm always a little intimidated when someone asks how to do something in papyrus and I have a suggestion which I'd like to share (helping people is cool) but I suspect it'll be an awkward way of doing things and I just know someone like Steve or Ez0n3 will come along sooner or later and bust out an awesome way of doing it and make me feel like a total hack - but at the same time that's how both I and the asker learn something new. So I just suck it up and post anyway. I'm still fuzzy on the whole states thing (gotostate does not mean leave the current state immediately? WTF) and the CK wiki isn't the most helpful on the subject of states (which is why I initially avoided them), but these examples have helped a lot. Edited November 16, 2012 by acidzebra Link to comment Share on other sites More sharing options...
Recommended Posts