steve40 Posted April 26, 2012 Share Posted April 26, 2012 Ps. I've been told that if you don't tick "Complete Quest", the quest will run at every game start, and every game load. Can anyone verify this? Not correct. The script will only run once on each new game. If the game is saved and reloaded the script doesn't run again. The only way to make the script run again is to stop and reset the quest. The exception might be if your script registered for updates. If you didn't unregister the update then the update block might continue to be called across saved games??? If you need to run some code at every game load, then one way would be to put that script on an ability/spell/object (see my previous posts) and use Grey79's example above to run a Quest on startup. The Quest script will only run once but that is all you need to transfer the scripted object to the player's inventory as a quest item. A simple script fragment to AddItem() to the player is sufficient :) In a similar way you can add spells and abilities to quest aliases. I don't think you even need to use script fragments to do that, there are options in one of the quest forms that does it for you. Link to comment Share on other sites More sharing options...
Sparafucile Posted April 26, 2012 Share Posted April 26, 2012 Grey79's example will get the job done but a lot of it is unnecessary complication. If you want a script that runs whenever your plugin is activated for the first time, here is how to do that via a Quest:Create a new Quest.Enter an ID.Click OK to close the dialog.Reopen the quest and switch to the Scripts tab.Add a [New Script]. Give it a Name and mark it as Hidden.Edit the source...If you're making a plugin called MyMod, you might name your quest _MyMod and the script _MyMod_INIT. If so, here's what the script source will look likeScriptname _MyMod_INIT extends Quest Hidden Add a code block to handle the Init event like soScriptname _MyMod_INIT extends Quest Hidden Event OnInit() Debug.Notification("MyMod Initializing") EndEventIf you save your plugin now and run the game, you should see the message in the upper left corner of your screen. The message will not be repeated (script will not run again) unless you start a new game or load a save from before MyMod was active. Prefixing your quest and script names with an underscore isn't necessary but it will make them sort at the top of the list in the CK and your file system. Marking the script as Hidden is not necessary; it prevents it from appearing in the script list unless you check the Show Hidden box which usually means that it is not intended for reuse. What if you release a new version and need to change the script? If the script will never change and your mod will never be updated, then the above directions are sufficient. However, if you follow the above directions, view it in-game, save, then edit the existing script, your changed script will not be run because the game thinks it already ran it. You could create a new quest but that's not the best way. Better to plan ahead and build version control into your initialization quest. Here's how to do that:Edit the quest and switch to the Quest Stages tab.Add two stagesLeave the first as 0 and change the second to 1.Switch to the Scripts tab.Remove the existing script.Add a new script and edit it like so:Scriptname _MyMod_INIT0 extends Quest Hidden Event OnInit() If self.GetStage() == 0 Debug.Notification("MyMod v1.0 Initialize") self.SetStage(1) EndIf EndEventWhat this does is, if the quest is at stage 0 (never ran before), it will do it's thing and then set the quest to stage 1. You do not need to flesh out the stages at all by adding log entries or setting the flags. The stages just need to exist. If you save the plugin now and run the game, the message should appear. Save the game. Then do the following:Add another stage. If you already have 0 and 1, the new stage should be 2, etc.Add a new script:Scriptname _MyMod_INIT1 extends Quest Hidden Event OnInit() While self.GetStage() < 1 Utility.Wait(0.1) EndWhile If self.GetStage() == 1 Debug.Notification("MyMod v1.1 Initializing") self.SetStage(2) EndIf EndEvent What that does: if the quest is not at stage 1 yet, it means the first script is still running so we should wait until it's done. Then, we do our thing and set the quest to the next stage. If you save the plugin now, run the game, and Continue, you should see the v1.1 init message. If you load a previous save, you should see the v1.0 and v1.1 messages appear in order. Link to comment Share on other sites More sharing options...
steve40 Posted April 26, 2012 Share Posted April 26, 2012 What that does: if the quest is not at stage 1 yet, it means the first script is still running so we should wait until it's done. Then, we do our thing and set the quest to the next stage. If you save the plugin now, run the game, and Continue, you should see the v1.1 init message. If you load a previous save, you should see the v1.0 and v1.1 messages appear in order. So if my mod was at v100 (as an extreme example) and a user loads it for the first time, then they will be spammed with 100 "mod initialising" messages as the quest scripts walk through each stage? :armscrossed: Might be better to stick to the one stage and just do a "resetquest" from the console, perhaps.Or, if your mod adds a permanent item to the player's inventory at quest stage 0, you could have a small script on the item that displays the notification from its OnInit block. That script should run every time the game is loaded, I would think? Link to comment Share on other sites More sharing options...
Sparafucile Posted April 27, 2012 Share Posted April 27, 2012 So if my mod was at v100 (as an extreme example) and a user loads it for the first time, then they will be spammed with 100 "mod initialising" messages as the quest scripts walk through each stage?You'd actually keep debug messages in your released scripts?? They're in the example so you can see in-game that things are happening as intended during testing but should definitely be commented out or deleted from the release version. Might be better to stick to the one stage and just do a "resetquest" from the console, perhaps.Why would anyone use your mod if it required console commands (hacks) to function properly? Or, if your mod adds a permanent item to the player's inventory at quest stage 0, you could have a small script on the item that displays the notification from its OnInit block. That script should run every time the game is loaded, I would think?Why does a script need to run or start running each time the game is loaded? Is there state that is not saved by the game that needs to be re-set? Certainly some mods contain special items or spells to configure them but they are triggered when used by the player. Do you mean a script that registers for the Update event? If one of the scripts 'attached to' a stage does RegisterForUpdate, that will continue to receive updates and will not interfere with other scripts. Yes, one of the 'problems' is that Quest-based init script will normally be run once. Is that really a problem? I would think that behavior is usually desired instead of a difficulty. My example shows you how to make this behavior work to your benefit. Here's an example: YourMod v1 has an initialize quest with one script and stages 0, 1:Script_Init0: when stage is 0, do stuff now and set stage to 1YourMod v2 has the initialize quest with three scripts and stages 0 - 3. The init process now needs to RegisterForUpdate to react to changes sometime in the future. Also, you found some errors in Script_Init0 and need to be patched over.Script_Init0: when stage is 0, do stuff (bugfixed) now and set stage to 2Script_Init1: when stage is 1, fix bugs from old Script_Init0 now and set stage to 2Script_Init2: when stage is 2, RegisterForUpdate to do some stuff sometime, and set stage to 3Users of your mod that had v1, their game will do this when v2 runs for the first time:Script_Init0: not run because the game remembers it as already ranScript_Init1: runs because it's new; fixes bugs from old Script_Init0 that is saved into their gameScript_Init2: runs because it's new; OnUpdate runs on the set intervalUsers of your mod that never had v1, their game will do this when v2 runs for the first time:Script_Init0: run because it is new; does not contain the errors of v1Script_Init1: runs but does not execute its payload because stage is never 1Script_Init2: run because it is new; OnUpdate runs on the set intervalYourMod v3 has the initialize quest with four scripts and stages 0 - 4. There is even more stuff to do in your init process:Script_Init0: when stage is 0, do stuff (bugfixed) and set stage to 2Script_Init1: when stage is 1, fix bugs from old Script_Init0 and set stage to 2Script_Init2: when stage is 2, RegisterForUpdate to do some stuff sometime, and set stage to 3Script_Init3: when stage is 3, do more stuff now and set stage to 4I won't bother with the details of new users and users that had v1. Users that had v2, their game will do this when v3 runs for the first time:Script_Init0: not run; game remembers it as doneScript_Init1: not run; game remembers it as doneScript_Init2: still receives Update events if sometime has not yet occurredScript_Init3: run Link to comment Share on other sites More sharing options...
steve40 Posted June 28, 2012 Share Posted June 28, 2012 (edited) These two examples are better. ;) Edited June 28, 2012 by steve40 Link to comment Share on other sites More sharing options...
Recommended Posts