CompGuyJMB Posted February 21, 2018 Share Posted February 21, 2018 Hi Everyone, I'm still getting my bearings in the creation kit. I'm familiar with Object Oriented Programming (Visual Basic), but I'm having a heck of a time with Papyrus. I'm trying to design a script that will be attached to a device (a radio). The intent of the script is to check to see if the power generator (PowerSource) is turned on. If it is, the radio will be "allowed" turn on. If the power source is off, the radio will turn off and not be "allowed" to turn on. My script compiles successfully, but is not working as intended. It seems that it is stuck in the "PowerIsOff" state. I'm not sure if my OnPowerOn event is not working (or correct), or what's going on. It could even be the initial IsPowered check. Ideally, I'd prefer to use the EnableMarker for the PowerSource (and not the generator itself), but I haven't been able to find an OnEnable event in the Creation Kit documentation. I also added the below lines to my OnInit() section, but this didn't make a difference: RegisterForRemoteEvent (PowerSource, "OnPowerOn") RegisterForRemoteEvent (PowerSource, "OnPowerOff") I also tried the below after adding the RegisterForRemoteEvent lines: Event PowerSource.OnActivate(ObjectReference PowerSource) Any help is appreciated. Please try to walk me through your solution, as I'm new :) Script posted below: Scriptname JMBCheckForPower extends ObjectReference ObjectReference Property PowerSource Auto {Power Source Device ie Generator} ObjectReference Property DeviceToPower Auto {Device to Turn On / Off} Event OnInit() If (PowerSource.IsPowered()) GotoState ("PowerIsOn") Else GotoState ("PowerIsOff") EndIf EndEvent State PowerIsOff Event OnBeginState(string asOldState) DeviceToPower.BlockActivation(true) EndEvent Event OnActivate(ObjectReference DeviceToPower) Debug.MessageBox ("The Power Source is Off") EndEvent Event OnPowerOn(ObjectReference PowerSource) GotoState ("PowerIsOn") EndEvent EndState State PowerIsOn Event OnBeginState(string asOldState) DeviceToPower.BlockActivation(false) EndEvent Event OnActivate(ObjectReference DeviceToPower) Debug.MessageBox ("Enjoy Your Device!") EndEvent Event OnPowerOff() GotoState ("PowerIsOff") EndEvent EndState Link to comment Share on other sites More sharing options...
JonathanOstrus Posted February 21, 2018 Share Posted February 21, 2018 (edited) Ok the first issue is that you're registering for a remote event, but not providing the call back event. You have the Event OnPowerOn() and OnPowerOff() but those are for local to the object, not remotes. You need to use something like Scriptname JMBCheckForPower extends ObjectReference ObjectReference Property PowerSource Auto {Power Source Device ie Generator} ObjectReference Property DeviceToPower Auto {Device to Turn On / Off} Event OnInit() RegisterForRemoteEvent (PowerSource, "OnPowerOn") RegisterForRemoteEvent (PowerSource, "OnPowerOff") If (PowerSource.IsPowered()) GotoState ("PowerIsOn") Else GotoState ("PowerIsOff") EndIf EndEvent State PowerIsOff Event OnBeginState(string asOldState) DeviceToPower.BlockActivation(true) EndEvent Event OnActivate(ObjectReference DeviceToPower) Debug.MessageBox ("The Power Source is Off") EndEvent Event ObjectReference.OnPowerOn(ObjectReference akSender, ObjectReference akPowerGenerator) GotoState ("PowerIsOn") EndEvent EndState State PowerIsOn Event OnBeginState(string asOldState) DeviceToPower.BlockActivation(false) EndEvent Event OnActivate(ObjectReference DeviceToPower) Debug.MessageBox ("Enjoy Your Device!") EndEvent Event ObjectReference.OnPowerOff(ObjectReference akSender) GotoState ("PowerIsOff") EndEvent EndState ; Empty state placeholders may be required for remotes. I cannot remember. Event ObjectReference.OnPowerOn(ObjectReference akSender, ObjectReference akPowerGenerator) EndEvent Event ObjectReference.OnPowerOff(ObjectReference akSender) EndEvent Remote callbacks will always have the object type then the period and Event name. Then the parameters will be the same as normal for the event with the exception that an addition first parameter will be in from as the calling source object with its type. You can see more of this in the vanilla source of the FollowerScript.psc. It has 2 types being Actor and ReferenceAlias. FusionGeneratorPowerPuzzleScript.psc also has remotes for ObjectReference. Which is where I got the reminder that it may need the empty state placeholders. Edited February 21, 2018 by BigAndFlabby Link to comment Share on other sites More sharing options...
CompGuyJMB Posted February 21, 2018 Author Share Posted February 21, 2018 Thank you. I'm at work now, so I'll check when I get home. One more question though, in the States sections, should ObjectReference.OnPowerOn(ObjectReference akSender) Be ObjectReference.OnPowerOn(PowerSource akSender) Or PowerSource.OnPowerOn(ObjectReference akSender) How does the script know which device I want to check the OnPowerOn? I can see how this might work if only the PowerSource had an OnPowerOn event, but doesn't that event apply to all ObjectReference objects? Sorry for any typos, I'm on my phone :-) Link to comment Share on other sites More sharing options...
deadbeeftffn Posted February 21, 2018 Share Posted February 21, 2018 For remote events you'll get one more parameter than for local events: local: Event OnPowerOn(ObjectReference akSender) EndEvent remote: Event ObjectReference.OnPowerOn(ObjectReference akSender, ObjectReference akActionRef) EndEvent Link to comment Share on other sites More sharing options...
JonathanOstrus Posted February 21, 2018 Share Posted February 21, 2018 (edited) Hah as deadbeeftffn says remote events get an extra argument. Which is the object that the event is firing on. I corrected my post above as I didn't check the argument list previously. So in your case you registered for the events on PowerSource. PowerSource is the object sending the event to your script remotely. So... using the definition from CK wiki as a design basis: Event ObjectReference.OnPowerOn(ObjectReference akSender, ObjectReference akPowerGenerator) akSender would be your "PowerSource" ObjectReference.akPowerGenerator is the actual game ObjectReference making the power that is powering akSender. To be clear. If you register for remote events on other objects for the same OnPowerOn and OnPowerOff events. The same event triggers in this script will get all of the trigger calls. So you would then need to do an if tree to check which akSender it is to deal with it. Since your original script only specified one remote registration only one object would be sending events to you. Edited February 21, 2018 by BigAndFlabby Link to comment Share on other sites More sharing options...
CompGuyJMB Posted February 21, 2018 Author Share Posted February 21, 2018 Thanks for the input, deadbeeftffn . BigAndFlabby, I compiled your code as is above (after your edit), and it compiled no problem. You were right, the Empty State placeholders were required (I deleted them to try it, compiler complained). In game, I had the same problem as in my OP. Once the PowerSource was turned on, I went to activate the DeviceToPower (the radio), and it was still "stuck" in the PowerIsOff state. Was I supposed to rename something to one of my variable names? i.e. akPowerGenerator to PowerSource? I'm also wondering if it has to do with the IF statement in the OnInit event not being formatted properly (with the remote reference), so it goes to the PowerIsOff state by default? I will review the other examples you provided me and try to see what I'm missing. Wife's calling me to dinner :-). Any other ideas? Link to comment Share on other sites More sharing options...
CompGuyJMB Posted February 21, 2018 Author Share Posted February 21, 2018 (edited) I re-wrote my If statement as below, and was still stuck in the PowerIsOff state. If (PowerSource.IsPowered()==false) GotoState ("PowerIsOff") Else GotoState ("PowerIsOn") EndIf So, I tried writing my If statement "backwards", so that if the PowerSource was off, the radio would work. I got stuck in the PowerIsOn state. The only conclusion I can make is that it's not properly changing states - which would lead me back to the OnPowerOn and OnPowerOff events not working. If (PowerSource.IsPowered()) GotoState ("PowerIsOff") Else GotoState ("PowerIsOn") EndIf Edited February 21, 2018 by CompGuyJMB Link to comment Share on other sites More sharing options...
JonathanOstrus Posted February 22, 2018 Share Posted February 22, 2018 So I would conclude likely one of the following from what you're describing: 1) the object PowerSource is pointing to is in fact not powered.2) the object PowerSource is pointing to doesn't exist. IE property isn't set correctly.3) PowerSource isn't loaded and isn't persistent.4) whatever you're doing to test isn't causing PowerSource to change power state. Can you post the esp and source you're using so we could try ourselves. It's probably something simple but trying to think of every scenario is tough. Link to comment Share on other sites More sharing options...
deadbeeftffn Posted February 22, 2018 Share Posted February 22, 2018 (edited) PowerSource is defined to be a generator. Generators can be de/activated, though this does not change their 'isPowered' state. Only objects needing power to operate will change their 'onPower' state (DeviceToPower). ObjectReference Property DeviceToPower Auto {Device to Turn On / Off}Since the script should be attached to the radio (as far as i understand), you do not need this property. Therefore you may replace all occurences of "DeviceToPower" with "Self" Now the tricky part: ObjectReference Property PowerSource Auto {Power Source Device ie Generator} This can't work. An ObjectReference is an object that already exists. Since generators are usually placed in workshop mode, your script can't know the reference id of this newly placed generator beforehand. What you may try is to find out, if there is a generator connected to the workshop, and if yes, the radio may be activated. WorkshopParentScript Property WorkshopParent Auto Const import WorkshopDataScript import CommonArrayFunctions WorkshopScript workshopRef = WorkshopParent.GetWorkshopFromLocation(Self.GetCurrentLocation()) float power = workshopRef.GetValue(WorkshopParent.WorkshopRatings[WorkshopParent.WorkshopRatingPower].resourceValue) if (power > 0.0) ; we have power in our settlement Else ; no power here endif Edited February 22, 2018 by deadbeeftffn Link to comment Share on other sites More sharing options...
CompGuyJMB Posted February 22, 2018 Author Share Posted February 22, 2018 (edited) Hi deadbeeftffn, Thanks again for your input. I'll be uploading my ESP tonight. But to respond, the Generator is an object I placed using the Creation Kit. It is pre-existing when the cell loads. Your idea of checking for workshop power may be the ticket. The pre-existing generator is linked to the workshop via keyword. Your method will also allow the user to scrap my pre-existing generator and place their own (and not cause the script to fail because the previous generator no longer exists). I'll try that before uploading my ESP. Edit: For clarification, the generator is an activator. I have a toggle button enabling and disabling an enable marker, which also disables / enables the generator (and some lights). That all works OK. I have a static version of the generator in the same location so that it doesn't look weird when the generator is disabled. Edited February 22, 2018 by CompGuyJMB Link to comment Share on other sites More sharing options...
Recommended Posts