WhiteWolf424242 Posted January 4, 2021 Share Posted January 4, 2021 (edited) Hello, What do you think is the best method to limit dialogue script fragments to execute only the first time only? So that if the player tabs out of this dialogue and thus can initiate the topic again, the script fragment won't run the second time. What I don't want to do is manually store the information somewhere else (global, quest variable, some other script property) that it fired and then enclose the fragment code in an if for that value.I have a lot of such fragments that need to be "first time only", so I don't want to create many globals/quest variables for storing this information. I'd like to keep it local.Would it perhaps work to store the information in a private variable of the fragment?So for example, give the dialogue fragment script a bool Executed = false variable outside, and then modify the contents of the CK fragment code so that: If(!Executed) ; contents of the fragment Executed = true Endif Would this work? Or would the variable just reset to its initial value when the script runs the second time (thus preventing the condition from working?) This is the part that I'm unsure of. Do dialogue scripts retain the values of their variables, or are they reset to initials when they run the next time? Edited January 4, 2021 by WhiteWolf424242 Link to comment Share on other sites More sharing options...
IsharaMeradin Posted January 4, 2021 Share Posted January 4, 2021 If you want the dialog to still be present and available but not run any code, I suppose you could try to use a local variable. The proper way, in my opinion, would be with a global variable set as a condition for the topic info. When the variable is a different value the topic info is blocked. Two identical topic info choices can be created with different required global variable values. One would have the code and the other would not. The one with the code would require the initial value and set the global to the value required by the other. Link to comment Share on other sites More sharing options...
ReDragon2013 Posted January 4, 2021 Share Posted January 4, 2021 (edited) You asked: "What do you think is the best method to limit dialogue script fragments to execute only the first time?"It depends what is your aim like IsharaMeradin has explained. Next two fragment script samples: How to use? local Bool var ;BEGIN FRAGMENT CODE - Do not edit anything between this and the end comment ;NEXT FRAGMENT INDEX 1Scriptname TIF__000B924F extends TopicInfo Hidden ; "TIF__000B924F" is a sample only, its a pre-selected value made by CK ; https://forums.nexusmods.com/index.php?/topic/9476908-how-to-limit-fragments-to-run-only-once/ ;BEGIN FRAGMENT Fragment_0 Function Fragment_0(ObjectReference akSpeakerRef) Actor akSpeaker = akSpeakerRef as Actor ;BEGIN CODE IF ( bReady ) RETURN ; - STOP - bReady == TRUE, that means this fragment was already executed ENDIF ;--------------------- bReady = TRUE ; your fragment code here ;END CODE EndFunction ;END FRAGMENT ;END FRAGMENT CODE - Do not edit anything between this and the begin comment Bool bReady ; [default=False] globalVar ;BEGIN FRAGMENT CODE - Do not edit anything between this and the end comment ;NEXT FRAGMENT INDEX 1 Scriptname TIF__000B924F extends TopicInfo Hidden ; "TIF__000B924F" is a sample only, its a pre-selected value made by CK ;BEGIN FRAGMENT Fragment_0 Function Fragment_0(ObjectReference akSpeakerRef) Actor akSpeaker = akSpeakerRef as Actor ;BEGIN CODE IF (gTopicOnceOnly.GetValue() > 0.0) RETURN ; - STOP - this or any other fragment has changed the value of special globalVar ENDIF ;--------------------- gTopicOnceOnly.Mod(1.0) ; threadsafe ;;; gTopicOnceOnly.SetValue(1.0) ; your fragment code here ;END CODE EndFunction ;END FRAGMENT ;END FRAGMENT CODE - Do not edit anything between this and the begin comment GlobalVariable PROPERTY gTopicOnceOnly auto Conditional ; [default= .GetValue() == 0.0] like IsharaMeradin wrote: Set a global variable as condition for the topic info directly outside the script fragment. "When the 'variable' (the GlobalVariable) is a different value the topic info is blocked." Edited January 4, 2021 by ReDragon2013 Link to comment Share on other sites More sharing options...
WhiteWolf424242 Posted January 4, 2021 Author Share Posted January 4, 2021 Okay, I tested it, and the local variable way simply doesn't work.After the dialogue ends these scripts stop, and when scripts stop local data is lost. When the dialogue is started again, the script restarts and bReady initializes back to its default value.Therefore if(bReady) is always false, no matter how many times the code has run before it. Thanks for the code samples, but I know how to store it and set it up with external tools like globals I just really, really wanted to avoid it. I've got at least 15 of these fragments, and I didn't want to make 15 global variables for this. These are also edited vanilla dialogues actually and the topic info is not shared, so duplicating everything is again something I didn't want to spend time with. But unless there is some kind of "static" variable option, that survives when it's parent script stops, it looks I have no choice but to do it the arduous way. :/(Seriously though, given the fact the player can tab out of a dialogue, Bethestda should have added "first time only" support for these fragments in the first place, in my opinion. ) Thanks anyway :) Link to comment Share on other sites More sharing options...
ReDragon2013 Posted January 5, 2021 Share Posted January 5, 2021 (edited) Ok.. you tested the local var fragment script, and it does not work. Well.. what do you think about a quest script as common storage for topic fragments. sample fragment script ;BEGIN FRAGMENT CODE - Do not edit anything between this and the end comment ;NEXT FRAGMENT INDEX 1Scriptname TIF__000B924F extends TopicInfo Hidden ; "TIF__000B924F" is a sample only, its a pre-selected value made by CK ; https://forums.nexusmods.com/index.php?/topic/9476908-how-to-limit-fragments-to-run-only-once/ ;BEGIN FRAGMENT Fragment_0 Function Fragment_0(ObjectReference akSpeakerRef) Actor akSpeaker = akSpeakerRef as Actor ;BEGIN CODE ww42StorageQuestScript ps = self,GetOwningQuest() as ww42StorageQuestScript IF ps.myF_IsDone(0x000B924F) ; as parameter use the same ID of topicInfo, Keep in mind this approach is limited to one fragment per topicInfo script RETURN ; - STOP - "function returns TRUE, that means this fragment was already executed" ENDIF ;--------------------- ; your fragment code here ;END CODE EndFunction ;END FRAGMENT ;END FRAGMENT CODE - Do not edit anything between this and the begin comment sample quest script, which is using int array Scriptname ww42StorageQuestScript extend Quest ; https://forums.nexusmods.com/index.php?/topic/9476908-how-to-limit-fragments-to-run-only-once/ Int[] a ; this is undefined array of integer, should never reset while quest is running ; -- EVENT -- EVENT OnInit() a = new Int[128] ; make the array reliable by initialization (you are limited to maximum of 128 topicinfo fragments) Debug.Trace(" OnInit() - has been called for " +self) ENDEVENT ; -- FUNCTION -- ;------------------------------ Bool FUNCTION myF_IsDone(Int n) ; internal helper will be called by topic fragments ;------------------------------ int i = a.Find(n) ; look for existing array entry IF (i >= 0) ; "entry was found, that means this function was called at least a second time from topicInfo fragment" Return TRUE ENDIF ;-------------- "now we run a while loop to find first unused array entry to put the function paramter into" i = 0 WHILE (i < 128) ; max array length was made by 128, see OnInit() IF (a[i] == 0) a[i] = n ; set new entry i = 128 ; abort while loop ENDIF i = i + 1 ENDWHILE ; "this function was called first time from fragment with parameter 'n', so run the fragment code" Return False ENDFUNCTION Make sure you attach the quest script to the right quest and script name is matching overall. Edited January 5, 2021 by ReDragon2013 Link to comment Share on other sites More sharing options...
WhiteWolf424242 Posted January 5, 2021 Author Share Posted January 5, 2021 Yeah, using an array of formIDs does cut down the work quite a bit, I wonder why I haven't thought of that. Thanks :) Link to comment Share on other sites More sharing options...
Recommended Posts