DaveLessnau Posted December 16, 2013 Share Posted December 16, 2013 (edited) I've got two FO3 mods that use FOSE. I put a check for it at the start of my scripts in both mods. For instance: if GetFOSEVersion ; checks to see if FOSE is present (required) [do stuff] else ;If FOSE isn't running, display a warning and set things up to quit ShowMessage DALCOJOMFoseWarningMessage endif ;done with FOSE existence check My other mod's script is similar. If FOSE is present, the scripts run fine. But, I've just noticed that if FOSE is not present, the ELSE side of the scripts don't run. IOW, I get no warning messages. The scripts don't run (at least I assume so since nothing bad (or good) happens). But those messages (which exist) don't show up. For the life of me, I can't see why. The scripts validate just fine at Cipscis' script validator. With FOSE on, typing GetFOSEVersion in the console gives me a 1 (as expected). With it turned off, that same console command gives me a message about "GetFOSEVersion not found" (again, as expected). In the scripts, I even tried specifying a value in the conditional. IOW: if GetFOSEVersion >= 1 just in case it didn't like whatever is returned when that command is run from a script. Same result. Any ideas? And I've attached a screenshot of what the particular message in the above code looks like in the GECK. EDIT: I've developed a simple mod that shows exactly what's happening: http://www.nexusmods.com/fallout3/mods/19970/? All it does is detect if FOSE is present. If so, it displays a message giving version information. If not, it displays a message saying so. As with my other FOSE checks, it works fine with FOSE present but does nothing with it missing. I'd really appreciate it if you either install the thing and see for yourself. Or, just read my Programming Notes section of the mod's Description page. I'd really like to figure this out. Edited December 17, 2013 by DaveLessnau Link to comment Share on other sites More sharing options...
pkleiss Posted December 17, 2013 Share Posted December 17, 2013 (edited) The reason that your script isn't running properly is becasue you are using a FOSE command to check for FOSE. Of course, if FOSE isn't running, that command borks the script. I performed the FOSE check using two quests with two quest scripts, UCFOSECheck and UCFOSEOn. scn UCFOSECheckScript Begin GameMode Set UCFOSEOn.Fosever to getfoseversion End SCN UCFOSEOnScript Short FOSEver Short DoOnce Begin GameMode If DoOnce If Fosever == 0 Showmessage UCFOSEMSG1 Else StopQuest UCFOSECheck StopQuest UCFOSEOn Endif Else Set DoOnce to 1 Endif EndThe reason this setup works is that I define a script variable in one script (the second script), but don't run any FOSE commands within it. I check for FOSE in the first script and if FOSE isn't running and the script borks, it has no effect on the variable (FOSEver) defined in the second script. If FOSE is running, it explicitly modifies FOSEver. So if FOSEver = 0, there is no FOSE, if FOSEver != 0, there is. If the first script borks, the variable used to determine if FOSE is running won't bork because it is not defined within the script that borked. NOTES: Both script are start game enabled, but the first script has a processing delay of 3 seconds while the second script has a delay of 10 seconds. This ensure that the first script has had time to run before the seconds script checks the value of FOSEver. Edited December 17, 2013 by pkleiss Link to comment Share on other sites More sharing options...
DaveLessnau Posted December 17, 2013 Author Share Posted December 17, 2013 By "bork the script," you mean the script just stops working? I assumed that GetFOSEVersion would return NULL if FOSE weren't running and the conditional would evaluate to FALSE. Failing a NULL value, that's why I tried testing for a specific value of 1. If the script just stops when FOSE's not running..... Well, ouch. It's really odd that the FOSE team didn't mention that in their readme. All they say there is: "When your mod loads, use the command GetFOSEVersion to make sure a compatible version of FOSE is installed. In general, make sure you are testing for any version later than the minimum version you support, as each update to FOSE will have a higher version number. Something like:if GetFOSEVersion < 5 MessageBox "This mod requires a newer version of FOSE."endif" I guess they just assumed SOME version of FOSE was installed instead of NO version. Without any version of FOSE running, that test would never display anything to the user. Sigh. I'm going to have to work through your scripts and explanations. Once I think I understand what's happening, I'll try implementing that in the DALCOFOSECheck mod I just set up (since it's easy) and see if I get it right. Thanks. Link to comment Share on other sites More sharing options...
pkleiss Posted December 17, 2013 Share Posted December 17, 2013 (edited) Hehe! I used to say 'script crashes' but every one else kept referring to that as 'borked.' But yeah, the script will freeze if using a FOSE command without FOSE being installed. Before I implemented those two scrips, I kept getting complaints that my mod wasn't working at one specific point. It took me quite a while to figure out that the reason was that people were loading my mod without FOSE even though it was a requirement. When their game failed, it was becasue they had gotten to that part of the mod where they first encountered a FOSE script and that script wasn't working. With these two scripts, if FOSE is not installed, the user will get a pop up message saying so every 10 seconds. If they don't install FOSE, it becomes quite annoying, but at least I stopped getting all these complaints about my mod. If it wasn't clear before, I'll try to explain again... My two script process works becasue the main script does not use any FOSE commands. It will work with or without FOSE. Within that script I define a variable that I reference from within the second script. The second script has the FOSE command that checks for the FOSE version. If FOSE is installed, the variable from the first script will be set in the second script to something not zero. If FOSE is not installed, the second script will crash and the variable defined in the first script will simply remain unchanged, by default, that is zero. Edited December 17, 2013 by pkleiss Link to comment Share on other sites More sharing options...
DaveLessnau Posted December 17, 2013 Author Share Posted December 17, 2013 I'd like to thank you again for this. I thought it through last night and like it. Do you have any problem with my incorporating your method into my mods? Link to comment Share on other sites More sharing options...
pkleiss Posted December 18, 2013 Share Posted December 18, 2013 Of course you can use it, that's why I posted it. The bottom line is, if you want your mod to automatically check if FOSE is installed, you'd have to use some form of a two-quest-scripts method to get it to work. Link to comment Share on other sites More sharing options...
luthienanarion Posted December 19, 2013 Share Posted December 19, 2013 A potential problem can occur if the user loads the mod with FOSE, saves, and loads that save without FOSE later. You should check for FOSE each time the game loads. Here's how I handle FOSE detection in my mods: To emulate GetGameRestarted, I use a global variable constant set to 0. The value of a global constant can be changed during a game session, but the value reverts when that session ends. To perform the check, I call a quest stage result script using SetStage. If the result script hangs because it calls a FOSE function without it loaded, the originating script continues as if it completed normally. Example result script: set hasFOSE to 0 set hasFOSE to GetFOSEVersion Example quest script: if(gameRestartGlobal == 0) set gameRestartGlobal to 1 setstage SomeQuest 0 if(hasFOSE) ; Do stuff that requires FOSE. else showmessage FOSErequiredMSG endif endif Link to comment Share on other sites More sharing options...
DaveLessnau Posted December 19, 2013 Author Share Posted December 19, 2013 (edited) Just to clariy, pkleiss' method doesn't set a token or variable, and unless the two scripts get marked Complete, the check will re-run every time a game is reloaded. That said, I like your method. It looks like it would avoid the length of time it takes to do a check inherent in the other method. So, it could be used to check only whenever a script using FOSE functions was starting to run. Have you noticed any timing issues (i.e., the "IF hasFOSE" executing before the SomeQuest stage can get up and running and set the variable to it's current value)? EDIT: I double-checked the bit about pkleiss' version not catching a FOSE change on re-loading a save. I was wrong. As you said, it doesn't. I'm going to have to take a look at the quests and see if they can be restarted (I had thought that not marking them Complete would do it). Thanks. Edited December 19, 2013 by DaveLessnau Link to comment Share on other sites More sharing options...
DaveLessnau Posted December 20, 2013 Author Share Posted December 20, 2013 (edited) Example result script: set hasFOSE to 0 set hasFOSE to GetFOSEVersion Example quest script: if(gameRestartGlobal == 0) set gameRestartGlobal to 1 setstage SomeQuest 0 if(hasFOSE) ; Do stuff that requires FOSE. else showmessage FOSErequiredMSG endif endif Some thoughts/questions: First, the majority of the work is in what you called an "Example quest script." You later call "setstage SomeQuest 0". In this example, is the "Example quest script" actually called "SomeQuest"? Is the script where most of the work done attached to the Quest Data Tab here? And is the Stage 0 you're referencing also in this same quest? Second, I had wondered why you used "setstage SomeQuest 0" instead of something like "StartQuest SomeQuest". But, if my assumption that most of this work is being done in a script attached to SomeQuest at the Quest Data Tab is correct, that would answer that. Also, I see in the GECK that The stage result script will be processed immediately after the SetStage call. The main script containing the SetStage call will be halted until the result script is finished. It is even possible to use the SetStage command inside a stage result script. In this case the new stage result script will run in place of the SetStage command and the old stage result script will continue after the new one has finished. Unlike Activate, it seems that any number of recursive SetStages are allowed (at least 250, tested from the same quest, are possible).That answers my earlier question about timing issues. So, that's great. And, finally, I had been wondering about somehow stopping the quest stage if its script failed from the lack of FOSE. I don't see any way to do that. But, from that GECK quote above, it looks like it's not an issue since "any number of recursive SetStages are allowed." Plus, with your global constant variable, that stage should only be activated once per loaded game. EDIT: I also assume that your variable "hasFOSE" is declared in the main quest script before the if statement. Edited December 20, 2013 by DaveLessnau Link to comment Share on other sites More sharing options...
luthienanarion Posted December 20, 2013 Share Posted December 20, 2013 In the examples, SomeQuest is the EditorID of the quest that has the stage defined with the result script. I usually just define a stage for the same quest that my quest script is attached to, but it can be a separate quest if you'd rathe arrange things that way. If the result script crashes (as when it encounters a FOSE function without FOSE loaded), it immediately halts and execution continues after the SetStage command. The result script sets the FOSE variable to 0 before using GetFOSEVersion so that it has a boolean FALSE value if GetFOSEVersion crashes. 'hasFOSE' is a global variable in this context, but you can use a quest variable as long as you refer to it using the Quest.Variable syntax (ex: set SomeQuest.hasFOSE to GetFOSEVersion), because the quest script's variables are not local in scope to the result script. Link to comment Share on other sites More sharing options...
Recommended Posts