Cylentnyte Posted August 4, 2011 Share Posted August 4, 2011 Hi all. Working on getting this script done partly for practice and partly for actual usage in the beginning of the mod. Basically you activate a generator on the ground and can repair it using a fission battery or 40+ Science. Once it's repaired it unlocks the terminal next to it and sets a global variable (for whether the generator was repaired or not) to 1. There's also a global for whether the station's main power source is turned on or not. If it is, it will make a coil of wire with an unused battery "enable" on the floor, and make the wire and cable seen when the generator's in use "disable". Also, if the generator was repaired, the unused battery on the floor will "disable" too. I know this is all overly complicated for a simple situation but like I said I want practice. Anywho, this isn't the main problem. As soon as I load the game, I get the message that should normally only pop up after I try to fix the generator without having any batteries on me. I click "ok", it pops up again. And again. Infinite loop. Checked over the logic as much I could and encased all the conditionals but couldn't figure it out. Probably something stupid I missed. Any help would be appreciated. Thanks. SCN ISSObservationGeneratorScript Short sButtonPressed Short sBatteryCount Short sScienceLevel Begin OnActivate if (IsActionRef Player) Set sBatteryCount to Player.GetItemCount 00033bc6 Set sScienceLevel to Player.GetActorValue Science if (ISSObservationGeneratorRepaired == 1) ShowMessage ISSObservationGeneratorRepairedMsg ;Generator already repaired elseif (ISSObservationGeneratorRepaired == 0) ShowMessage ISSObservationGeneratorMsg ;Regular message box with options to fix endif endif End Begin GameMode if (ISSPowerEnabled == 1) ISSGeneratorBatteryInUseREF.Disable ISSGeneratorWireInUseREF.Disable ISSGeneratorBatteryUnusedREF.Enable ISSGeneratorWireUnusedREF.Enable elseif (ISSPowerEnabled == 0) ISSGeneratorWireInUseREF.Enable ISSGeneratorWireUnusedREF.Disable ISSGeneratorBatteryUnusedREF.Disable if (ISSObservationGeneratorRepaired == 1) ISSGeneratorBatteryInUseREF.Enable elseif (ISSObservationGeneratorRepaired == 0) ISSGeneratorBatteryInUseREF.Disable endif endif if (sButtonPressed == -1) Return elseif (sButtonPressed == 0) ;Player chose to replace battery if (sBatteryCount == 0) ;Player doesn't have a fission battery ShowMessage ISSObservationGeneratorNoPartsMsg elseif (sBatteryCount >= 1) ;Player has a fission battery ShowMessage ISSObservationGeneratorSuccessMsg Player.RemoveItem 00033bc6 1 set ISSObservationGeneratorRepaired to 1 ISSGeneratorBatteryInUseREF.Enable ISSLaunchPadControlTerminalREF.Unlock endif elseif (sButtonPressed == 1) ;Player chose to refurbish if (sScienceLevel < 40) ;Player isn't skilled enough to refurbish ShowMessage ISSObservationGeneratorScienceFailMsg elseif (sScienceLevel >= 40) ;Player has required skill ShowMessage ISSObservationGeneratorScienceSuccessMsg set ISSObservationGeneratorRepaired to 1 ISSGeneratorBatteryInUseREF.Enable ISSLaunchPadControlTerminalREF.Unlock endif elseif (sButtonPressed == 2) ;Player leaves generator alone endif End Link to comment Share on other sites More sharing options...
Skevitj Posted August 4, 2011 Share Posted August 4, 2011 (edited) "00033bc6" -> You should be using the ObjectID to refer to an object in a script, not what you think the FormID will be. (FormIDs being modified by the load order... for objects in the main esm it will rarely be a problem, but is still very bad practice) AFAIK: "If" statements need a logic test to test true, they don't count >0 values as being true like some languages, hence "IsActionRef Player" would be "IsActionRef Player == 1". But that exact same functionality can be achieved by using "Begin OnActivate Player" instead as the block start. In that case, the IsActionRef test isn't even needed. a second "Begin OnActivate" block can be added later if you want general functionality for other NPCs (It would include the PC too, but then you could sort them out). In the "if (ISSPowerEnabled == 1 )" block (including the elseif) the contents of one of the two blocks is going to run every frame, trying to enable and disable the references every frame, this is going to cause the objects to appear to flicker instead of just sitting there. Adding in a do-once style block which ensures that the appropriate code is only run once on change of ISSPowerEnabled is the easiest way to fix that up. You need to insert "set sButtonPressed to GetButtonPressed" just before the "if (sButtonPressed == -1)" line since you never actually set sButtonPressed anywhere in the script, so it's always going to be 0. You will also want to add in another check, such that the GetButtonPressed and subsequest code is only run after the message has been shown (with the check being cleared after a result box has run), since currently this will begin to operate any time a message pops up anywhere during the game. This is one of the 2 main bits causing the problems you're talking about. Running through the logic -> All variables start at 0, so[/font]elseif (ISSPowerEnabled == 0) ISSGeneratorWireInUseREF.Enable ISSGeneratorWireUnusedREF.Disable ISSGeneratorBatteryUnusedREF.Disable if (ISSObservationGeneratorRepaired == 1) ISSGeneratorBatteryInUseREF.Enable elseif (ISSObservationGeneratorRepaired == 0) ISSGeneratorBatteryInUseREF.Disable endif endif[font="Arial"]In this bit the elseif test will test true, as will the elseif test within the block. With this running, enabling and disabling the references every frame. [/font]elseif (sButtonPressed == 0) ;Player chose to replace battery if (sBatteryCount == 0) ;Player doesnt have a fission battery ShowMessage ISSObservationGeneratorNoPartsMsg elseif (sBatteryCount >= 1) ;Player has a fission battery ShowMessage ISSObservationGeneratorSuccessMsg Player.RemoveItem 00033bc6 1 set ISSObservationGeneratorRepaired to 1 ISSGeneratorBatteryInUseREF.Enable ISSLaunchPadControlTerminalREF.Unlock endif[font="Arial"]This section of the second block will always run since sButtonPressed is always 0. sBatteryCount may or may not be 0 depending on the PC having which ever object is assigned to "33bc6", but since that section of the code is going to be running constantly, even if the object hasn't been activated, it's always going to be 0, hence the no parts message every frame. There are a few more errors in various places, but those are most of the big ones. Edited August 4, 2011 by Skevitj Link to comment Share on other sites More sharing options...
Cylentnyte Posted August 5, 2011 Author Share Posted August 5, 2011 (edited) Wow I wasn't expecting nearly as detailed a reply as that, thank you so much :D I did have the "set sButtonPressed to GetButtonPressed" in there somewhere but eventually became an accidental casualty of editing. Got confused with the way Cipscis explained how the button would return -1 on the next iteration through GameMode before MenuMode takes over and wasn't quite sure where to put GetButtonPressed. There's going to be a main breaker for the power in a "Systems Room" cell, but it's not the same one as the generator. I'm guessing I can't put the enabling/disabling block inside the OnActivate script for the breaker because of the cell difference? That would be one way to do it I guess. Also had "Begin OnActivate Player" in there before too but misread the GECK page on it and assumed it wouldn't be any different from just "Begin OnActivate", so will be redoing that. Cheers EDIT: Went over everything you said and finally got it working! Only other thing I did was move the message box option indexes around so 0 would be to "Leave it alone", would mean an uninitialized variable would default to that and avoid another loop. Finals results: SCN ISSObservationGeneratorScript Short sButtonPressed Short sScienceLevel Short sPowerStatusSentinel Short sMsgSentinel Begin OnActivate Player Set sScienceLevel to Player.GetActorValue Science if (ISSObservationGeneratorRepaired == 1) ShowMessage ISSObservationGeneratorRepairedMsg elseif (ISSObservationGeneratorRepaired == 0) ShowMessage ISSObservationGeneratorMsg set sMsgSentinel to 1 endif End Begin GameMode if (sPowerStatusSentinel != ISSPowerEnabled) if (ISSPowerEnabled == 1) ISSGeneratorBatteryInUseREF.Disable ISSGeneratorWireInUseREF.Disable ISSGeneratorBatteryUnusedREF.Enable ISSGeneratorWireUnusedREF.Enable elseif (ISSPowerEnabled == 0) ISSGeneratorWireInUseREF.Enable ISSGeneratorWireUnusedREF.Disable ISSGeneratorBatteryUnusedREF.Disable if (ISSObservationGeneratorRepaired == 1) ISSGeneratorBatteryInUseREF.Enable elseif (ISSObservationGeneratorRepaired == 0) ISSGeneratorBatteryInUseREF.Disable endif endif set sPowerStatusSentinel to ISSPowerEnabled endif if (sMsgSentinel == 1) set sButtonPressed to GetButtonPressed if (sButtonPressed == -1) Return elseif (sButtonPressed == 1) ;Player chose to replace battery ShowMessage ISSObservationGeneratorSuccessMsg Player.RemoveItem FissionBattery 1 ISSGeneratorBatteryInUseREF.Enable ISSLaunchPadControlTerminalREF.Unlock set ISSObservationGeneratorRepaired to 1 set sMsgSentinel to 0 elseif (sButtonPressed == 2) ;Player chose to refurbish if (sScienceLevel < 40) ;Player isn't skilled enough to refurbish ShowMessage ISSObservationGeneratorScienceFailMsg set sMsgSentinel to 0 elseif (sScienceLevel >= 40) ;Player has required skill ShowMessage ISSObservationGeneratorScienceSuccessMsg ISSGeneratorBatteryInUseREF.Enable ISSLaunchPadControlTerminalREF.Unlock set ISSObservationGeneratorRepaired to 1 set sMsgSentinel to 0 endif else set sMsgSentinel to 0 endif endif End Edited August 5, 2011 by sphinx275 Link to comment Share on other sites More sharing options...
Skevitj Posted August 6, 2011 Share Posted August 6, 2011 (edited) If the "breaker" object (placed in the game world) is marked as persistent, then you can call enable/disable on it from this script. I'm not 100% sure, but I believe the way to do it properly is to place an x-marker in the cell (same as the breaker object), and set it as the "parent" of the object. You then enable/disable the x-marker from this script and the "child object" (being the breaker object) is set to copy it's enabled/disabled state from the parent. Only problem I can see in your latest is that you're removing a fission battery, without ever checking to see if they have one. The scripting around sBatteryCount from your first script was correct (assuming you change the FormID -> ObjectID), so just copy/pasting that should fix that up. Edited August 6, 2011 by Skevitj Link to comment Share on other sites More sharing options...
Cylentnyte Posted August 6, 2011 Author Share Posted August 6, 2011 Sounds good. I figure though it would be cleaner to just keep the ISSPowerEnabled global there and have each object/activator that uses it to essentially listen for it's state to change. That way all the breaker does is change the variable to a 1 and anything listening for it automatically changes. Also a versatility bonus as any new object added in could just listen to that variable instead of editing the breaker script directly. As for the fission battery, I forgot to say I added a condition check to the message index for using a battery. If the player doesn't have one, the message option to replace it won't even appear. Thanks again! Link to comment Share on other sites More sharing options...
Skevitj Posted August 7, 2011 Share Posted August 7, 2011 Sounds good so far, just gimme a yell if you need help with anything else. Link to comment Share on other sites More sharing options...
Cylentnyte Posted August 8, 2011 Author Share Posted August 8, 2011 Will do, I'll be back for things here and there. Kudos given :D Link to comment Share on other sites More sharing options...
Recommended Posts