Jump to content

Custom Recruitment Radio Beacon (scripting help)


pepperman35

Recommended Posts

Okay, scripting warriors I have another question for you.

 

Background: I want to use the RelayTowerPublic [aka Radio tower 3SM-U81 (RelayTower01ext cell)] as a custom recruitment radio beacon for my settlement, which will be activated by a terminal. I’d like for the beacon to become active once the antennas are deployed and deactivate when the antenna are retracted.

 

Actions Take: The Relay Tower is added with the following keyword: WorkshopRadioObject, and the following actor values: PowerRadiation(1500), WorkshopRatingRadio(1), and WorkshopResourceObject(1). Ref links, scripts and fragment match those from RelayTower01ext cell. Currently, my version works just like the one in cell RelayTower01ext (i.e., antenna deploy and retract on command via the terminal). However, it is unclear to me where and how to get the rest of it to work (broadcast signal as desired).

 

Help Requested (scripting): What do I need to do in order to get the beacon to broadcast signal when the antennas are deployed (i.e., Tower is in the up position) and stop broadcasting signal when the antennas are retracted (i.e. Tower is in the down position).

 

Any help would be welcomed and most appreciated.

 

Link to comment
Share on other sites

After looking at the WorkshopObjectScript and the WorkshopParentScript, I decided to start small. I added the WorkshopRadioBeacon and a default terminal into the mod. Within the terminal I added the two menu items: Activate Radio Beacon and Deactivate Radio Beacon. I added a property with the following values:

  • Property Name: myBeacon
  • Type: ObjectReference
  • Value: Pointed it to the Radio Beacon

 

For a simple Papyrus Fragment I used myBeacon.SetOpen(false) for the Activate Radio Beacon menu item and myBeacon.SetOpen(true).

In game, I manually added a small generator to power the Radio Beacon, tested it manually to confirm it was working and then shut it down via the switch. I then tried using the terminal to turn the radio beacon on and the switch light turns green, and there is an audio of the switch activating; however, no signal was apparently being broadcast. At this point I am at a loss on how to proceed. I fast traveled away and back. Repeated the process but the results were the same ...no broadcast signal via the terminal. Any pointers.

Link to comment
Share on other sites

Can't remember exactly what it was, but there is code for this whole radio thing in the WorkshopObject script. You will most definitely need to extend it. I think there was either a bool property or a function which returns bool, which determines whenever the radio is on or not. Search for "radio" in the file.

Link to comment
Share on other sites

Thanks for the reply.

 

In the WorkshopObjectScript there is the event

 

Event OnActivate(ObjectReference akActionRef)
;WorkshopParent.wsTrace(self + " activated by " + akActionRef + " isradio?" + HasKeyword(WorkshopParent.WorkshopRadioObject))
if akActionRef == Game.Getplayer()
;WorkshopParent.wstrace(self + " activated by player")
if CanProduceForWorkshop()
if HasKeyword(WorkshopParent.WorkshopRadioObject)
; radio on/off
; toggle state
bRadioOn = !bRadioOn
WorkshopParent.UpdateRadioObject(self)
endif
else
endif
; player comment
if IsBed() == false
WorkshopParent.PlayerComment(self)
endif
endif
if GetBaseObject() as Flora
SetValue(WorkshopParent.WorkshopFloraHarvestTime, Utility.GetCurrentGameTime())
endif
EndEvent
Inside the WorkshopParentScript there is the function ...
function UpdateRadioObject(WorkshopObjectScript radioObject)

wsTrace("UpdateRadioObject for " + radioObject)

WorkshopScript workshopRef = GetWorkshop(radioObject.workshopID)

; radio

if radioObject.bRadioOn && radioObject.IsPowered()

wsTrace(" starting radio station")

; make me a transmitter and start radio scene

; 1.6: allow workshop-specific override

if workshopRef.WorkshopRadioRef

workshopRef.WorkshopRadioRef.Enable() ; enable in case this is a unique station

radioObject.MakeTransmitterRepeater(workshopRef.WorkshopRadioRef, workshopRef.workshopRadioInnerRadius, workshopRef.workshopRadioOuterRadius)

if workshopRef.WorkshopRadioScene.IsPlaying() == false

workshopRef.WorkshopRadioScene.Start()

endif

else

radioObject.MakeTransmitterRepeater(WorkshopRadioRef, workshopRadioInnerRadius, workshopRadioOuterRadius)

if WorkshopRadioScene01.IsPlaying() == false

WorkshopRadioScene01.Start()

endif

endif

if workshopRef.RadioBeaconFirstRecruit == false

WorkshopEventRadioBeacon.SendStoryEvent(akRef1 = workshopRef)

endif

else

wsTrace(" stopping radio station")

radioObject.MakeTransmitterRepeater(NONE, 0, 0)

; if unique radio, turn it off completely

if workshopRef.WorkshopRadioRef && workshopRef.bWorkshopRadioRefIsUnique

wsTrace(" custom station: disabling transmitter")

workshopRef.WorkshopRadioRef.Disable()

; stop custom scene if unique

workshopRef.WorkshopRadioScene.Stop()

endif

endif

; send power change event so quests can react to this

workshopRef.RecalculateWorkshopResources()

SendPowerStateChangedEvent(radioObject, workshopRef)

endFunction

 

 

So how do I change the bRadioOn variable and send it back to the function via a Papyrus Fragment? I tried defining the variable bool Property bRadioOn = true auto hidden to start and it didn't like that. Rather a noob when it comes to scripting.

Link to comment
Share on other sites

I implemented a custom radio beacon in the next update (not published so far) to my "forest grove water lock" mod. Basically reused an existing made a new object based on the workshop beacon, gave it a different NIF (invisible or whatever), made it self powered and powered on by default (keywords) and then controlled the beacon ON/OFF by enable()/disable() it. Had to add a small script to activate() it on load, it's posted below.

Link to comment
Share on other sites

Ok, here's my activator script. It's really simple:

Scriptname ForestGroveSluice:FGS_RecruitmentBeaconActivator extends ObjectReference
 
; custom scripting by niston
 
Event OnLoad()
    If !(IsDisabled())
        Self.Activate(Game.GetPlayer(), true)
    EndIf 
EndEvent
Link to comment
Share on other sites

So I've had a quick look at RelayTowerScript.psc and it's state based.

 

You should be able to make a control script that registers for remote OnBeginState event on RelayTowerScript. This event will inform the control script whenever the relay tower script enters a new state. If the new state is DownPosition, the tower is retracted. If new state is UpPosition, the tower is extended. It could also be MovingUp *while* its extending, or MovingDown *while* it's retracting, but these are probably not relevant to your use case.

 

This mechanism will also initialize "automagically" because the DownPosition is auto state. Nice!

 

The control script may then simply enable the custom recruitment beacon on receiving UpPosition and disable it on receiving DownPosition. Something like this perhaps:

Scriptname RTRB_ControlScript extends ObjectReference

; custom scripting by niston

ObjectReference Property RecruitmentBeacon Auto Const
{ Pick Custom Recruitment Beacon reference in Render Window }

Event OnInit()
	; register OnBeginState event on RelayTowerScript attached to same reference we are attached to
	RegisterForRemoteEvent((((Self as ObjectReference) as RelayTowerScript) as ScriptObject), "OnBeginState")
EndEvent

Event OnLoad()
	; re-register remote event on load, make sure we dont stack up registrations
	UnRegisterForRemoteEvent((((Self as ObjectReference) as RelayTowerScript) as ScriptObject), "OnBeginState")
	RegisterForRemoteEvent((((Self as ObjectReference) as RelayTowerScript) as ScriptObject), "OnBeginState")
EndEvent

Event ScriptObject.OnBeginState(ScriptObject akSender, String oldState)
	; state change event received, decide based on current state 
	ScriptObject refRTSO = (((Self as ObjectReference) as RelayTowerScript) as ScriptObject)
	If (refRTSO.GetState() == "DownPosition")
		; tower is retracted, disable beacon
		Debug.Notification("Tower retracted")
		RecruitmentBeacon.Disable()
	ElseIf (refRTSO.GetState() == "UpPosition")
		; tower is extended, enable beacon
		Debug.Notification("Tower extended")
		RecruitmentBeacon.Enable()
	EndIf
EndEvent

Attach the script to the relay tower and fill out the RecruitmentBeacon property in CK and see if it works. I also suggest to not test with an invisible NIF for the custom recruitment beacon. This way, you can actually observe the beacon properly spawning into or vanishing from existence. You may always switch over to invisible.NIF later on, when stuff has been verified to work.

Link to comment
Share on other sites

Welp, I just tested the above and it doesn't work. LOL.

 

I really don't understand why though. The runtime error is:

 

error: [RelayTowerScript < (001D1AEA)>] does not receive "OnBeginState" events, registration request ignored

 

But the RelayTowerScript clearly does receive OnBeginState events, it even handles them. :huh:

Link to comment
Share on other sites

After dabbling around for a while, I fail to see why my above script doesn't work. It makes no sense.

 

Anyways, I made another one, working with OnAnimationEvent this time:

Scriptname RTRB_ControlScript extends ObjectReference

; custom scripting by niston

ObjectReference Property RecruitmentBeacon Auto Const
{ Pick Custom Recruitment Beacon reference in Render Window }

Event OnInit()
	; call setup procedure from OnInit event
	Debug.Trace(self + " - OnInit()")
	Setup()
EndEvent

Event OnLoad()
	; call setup procedure from OnLoad event
	Debug.Trace(self + " - OnLoad()")
	Setup()
EndEvent

Event OnAnimationEvent(ObjectReference akSource, String eventName)
	; animation event received
	Debug.Trace(self + " - Animation Event received")
	; update beacon according to current state
	UpdateBeacon()
EndEvent

Function Setup()
	; (re-)register animation event, make sure we dont stack up registrations
	UnRegisterForAnimationEvent(self, "done")
	If (RegisterForAnimationEvent(self, "done"))
		Debug.Trace(self + " - Animation Event registered succcessfully")
	Else
		Debug.Trace(self + " - Failed to register Animation Event")
	EndIf
	; update beacon according to current state
	UpdateBeacon()
EndFunction

Function UpdateBeacon()
	; enables/disables the RecruitmentBeacon, depending on wether the radio tower is extended or retracted
	RelayTowerScript refRTSO = ((Self as ObjectReference) as RelayTowerScript)
	If (refRTSO.GetState() == "DownPosition" || refRTSO.GetState() == "MovingDown")
		; tower is retracted, disable beacon
		Debug.Notification("Tower retracted; Disabling beacon...")
		RecruitmentBeacon.Disable()
	ElseIf ((refRTSO.GetState() == "UpPosition") || (refRTSO.GetState() == "MovingUp"))
		; tower is extended, enable beacon
		Debug.Notification("Tower extended; Enabling beacon...")
		RecruitmentBeacon.Enable()
	EndIf
EndFunction

Attach script to relay tower, fill out RecruitmentBeacon property. Tested it in my game and found it working. You might want to remove the Debug.Notification() calls in UpdateBeacon() function after testing.

 

Something else to be aware of: The relay towers retract on their own, after some time.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...