ArronDominion Posted April 26, 2017 Share Posted April 26, 2017 (edited) Hello everyone, I am more used to Skyrim than Fallout 4 in terms of scripting, and am running into a roadblock anytime I picked up the Fallout 4 Creation Kit for scripting. I am attempting to make a small quest mod where the player runs into Diamond City, and is greeted by a messenger bot with a message to go back to Vault 111. I have a logic cell setup with the required NPCs, and have an object reference in the cell with the following script: Scriptname AJDBTInitQuestController extends ObjectReference Quest Property AJDBTQuestForTheVaultTecHomebrew Auto Event OnInit() ;Game.GetPlayer().AddItem(AJDBTHolotape, 1) StartTimerGameTime(1) EndEvent Event OnTimerGameTime(int aiTimerID) if (AJDBTQuestForTheVaultTecHomebrew != None) ;Determine if we need to startup our Dialogue Controller if (!AJDBTDialogueController.IsRunning()) AJDBTDialogueController.Start() While (AJDBTDialogueController.IsStarting()) ;Spin EndWhile EndIf ;Ensure that the scene has not been done before if (AJDBTDialogueController.GetStage() < 1) ;Verify the distance Actor Player = Game.GetPlayer() If ((AJDBTDiamondCitySceneStartMarker.GetDistance(Game.GetPlayer()) <= 250.0)) ;Force first person Game.ForceFirstPerson() ;Disable player controls InputEnableLayer myLayer = InputEnableLayer.Create() myLayer.DisablePlayerControls(true, true, false, true, true, true, true, true, true, true, true) ;Give a notification that controls have been disabled Game.ShakeController(0.75, 0.75, 2) ;Move the eyebot AJDBTEyebotMessenger.Enable() AJDBTEyebotMessenger.MoveTo(AJDBTDiamondCityEntrance) ;Move everything else to kill each other in Vault 111 AJDBTVaultTecRoboticOperative.Enable() AJDBTVaultTecRoboticOperative.MoveTo(AJDBTVault111Marker) AJDBTLvlRaider.Enable() ;Figure out how many raiders to move to Vault | 2 by default If (Player.GetLevel() < 10) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 2) ElseIf (Player.GetLevel() < 20) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 3) ElseIf (Player.GetLevel() < 30) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 4) ElseIf (Player.GetLevel() < 40) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 5) ElseIf (Player.GetLevel() < 50) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 6) ElseIf (Player.GetLevel() < 60) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 7) Else AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 9) EndIf ;Start the Scene AJDBTDialogueControllerEyebotScene.ForceStart() EndIf Else ;Re-register the timer StartTimerGameTime(0.033) EndIf else ;Cancel our timer for sure CancelTimerGameTime() EndIf EndEvent Actor Property AJDBTVaultTecRoboticOperative Auto Holotape Property AJDBTHolotape Auto Actor Property AJDBTEyebotMessenger Auto Const Quest Property AJDBTDialogueController Auto Const Actor Property AJDBTLvlRaider Auto Const Scene Property AJDBTDialogueControllerEyebotScene Auto Const ObjectReference Property AJDBTDiamondCityEntrance Auto Const ObjectReference Property AJDBTDiamondCitySceneStartMarker Auto Const ObjectReference Property AJDBTLogicCellMarker Auto Const ObjectReference Property AJDBTVault111Marker Auto Const On my existing save (clean of mods), I go to the Diamond City location which is designed to trigger the quest after fast traveling from Far Harbor, but nothing is happening. Is there something I should be doing something different in the Fallout 4 scripting environment? Edited April 26, 2017 by Arron Dominion Link to comment Share on other sites More sharing options...
scrivener07 Posted April 26, 2017 Share Posted April 26, 2017 Try OnLoad instead of OnInit. http://www.creationkit.com/fallout4/index.php?title=OnLoad_-_ObjectReference Link to comment Share on other sites More sharing options...
Reneer Posted April 26, 2017 Share Posted April 26, 2017 (edited) The issue is likely that the player is further away than 250 from that marker and if that's the case your OnTimer exits and never registers itself again. The fix will be adding an else statement after your GetDistance call and calling StartTimerGameTime(0.033)in the else statement. Fixed code: Scriptname AJDBTInitQuestController extends ObjectReference Quest Property AJDBTQuestForTheVaultTecHomebrew Auto Event OnInit() ;Game.GetPlayer().AddItem(AJDBTHolotape, 1) StartTimerGameTime(1) EndEvent Event OnTimerGameTime(int aiTimerID) if (AJDBTQuestForTheVaultTecHomebrew != None) ;Determine if we need to startup our Dialogue Controller if (!AJDBTDialogueController.IsRunning()) AJDBTDialogueController.Start() While (AJDBTDialogueController.IsStarting()) ;Spin EndWhile EndIf ;Ensure that the scene has not been done before if (AJDBTDialogueController.GetStage() < 1) ;Verify the distance Actor Player = Game.GetPlayer() If ((AJDBTDiamondCitySceneStartMarker.GetDistance(Game.GetPlayer()) <= 250.0)) ;Force first person Game.ForceFirstPerson() ;Disable player controls InputEnableLayer myLayer = InputEnableLayer.Create() myLayer.DisablePlayerControls(true, true, false, true, true, true, true, true, true, true, true) ;Give a notification that controls have been disabled Game.ShakeController(0.75, 0.75, 2) ;Move the eyebot AJDBTEyebotMessenger.Enable() AJDBTEyebotMessenger.MoveTo(AJDBTDiamondCityEntrance) ;Move everything else to kill each other in Vault 111 AJDBTVaultTecRoboticOperative.Enable() AJDBTVaultTecRoboticOperative.MoveTo(AJDBTVault111Marker) AJDBTLvlRaider.Enable() ;Figure out how many raiders to move to Vault | 2 by default If (Player.GetLevel() < 10) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 2) ElseIf (Player.GetLevel() < 20) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 3) ElseIf (Player.GetLevel() < 30) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 4) ElseIf (Player.GetLevel() < 40) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 5) ElseIf (Player.GetLevel() < 50) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 6) ElseIf (Player.GetLevel() < 60) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 7) Else AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 9) EndIf ;Start the Scene AJDBTDialogueControllerEyebotScene.ForceStart() else ;Re-register the timer StartTimerGameTime(0.033) endif Else ;Re-register the timer StartTimerGameTime(0.033) EndIf else ;Cancel our timer for sure CancelTimerGameTime() EndIf EndEvent Actor Property AJDBTVaultTecRoboticOperative Auto Holotape Property AJDBTHolotape Auto Actor Property AJDBTEyebotMessenger Auto Const Quest Property AJDBTDialogueController Auto Const Actor Property AJDBTLvlRaider Auto Const Scene Property AJDBTDialogueControllerEyebotScene Auto Const ObjectReference Property AJDBTDiamondCityEntrance Auto Const ObjectReference Property AJDBTDiamondCitySceneStartMarker Auto Const ObjectReference Property AJDBTLogicCellMarker Auto Const ObjectReference Property AJDBTVault111Marker Auto Const Edited April 26, 2017 by Reneer Link to comment Share on other sites More sharing options...
ArronDominion Posted April 27, 2017 Author Share Posted April 27, 2017 (edited) The issue is likely that the player is further away than 250 from that marker and if that's the case your OnTimer exits and never registers itself again. The fix will be adding an else statement after your GetDistance call and calling StartTimerGameTime(0.033)in the else statement. Fixed code: Scriptname AJDBTInitQuestController extends ObjectReference Quest Property AJDBTQuestForTheVaultTecHomebrew Auto Event OnInit() ;Game.GetPlayer().AddItem(AJDBTHolotape, 1) StartTimerGameTime(1) EndEvent Event OnTimerGameTime(int aiTimerID) if (AJDBTQuestForTheVaultTecHomebrew != None) ;Determine if we need to startup our Dialogue Controller if (!AJDBTDialogueController.IsRunning()) AJDBTDialogueController.Start() While (AJDBTDialogueController.IsStarting()) ;Spin EndWhile EndIf ;Ensure that the scene has not been done before if (AJDBTDialogueController.GetStage() < 1) ;Verify the distance Actor Player = Game.GetPlayer() If ((AJDBTDiamondCitySceneStartMarker.GetDistance(Game.GetPlayer()) <= 250.0)) ;Force first person Game.ForceFirstPerson() ;Disable player controls InputEnableLayer myLayer = InputEnableLayer.Create() myLayer.DisablePlayerControls(true, true, false, true, true, true, true, true, true, true, true) ;Give a notification that controls have been disabled Game.ShakeController(0.75, 0.75, 2) ;Move the eyebot AJDBTEyebotMessenger.Enable() AJDBTEyebotMessenger.MoveTo(AJDBTDiamondCityEntrance) ;Move everything else to kill each other in Vault 111 AJDBTVaultTecRoboticOperative.Enable() AJDBTVaultTecRoboticOperative.MoveTo(AJDBTVault111Marker) AJDBTLvlRaider.Enable() ;Figure out how many raiders to move to Vault | 2 by default If (Player.GetLevel() < 10) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 2) ElseIf (Player.GetLevel() < 20) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 3) ElseIf (Player.GetLevel() < 30) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 4) ElseIf (Player.GetLevel() < 40) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 5) ElseIf (Player.GetLevel() < 50) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 6) ElseIf (Player.GetLevel() < 60) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 7) Else AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 9) EndIf ;Start the Scene AJDBTDialogueControllerEyebotScene.ForceStart() else ;Re-register the timer StartTimerGameTime(0.033) endif Else ;Re-register the timer StartTimerGameTime(0.033) EndIf else ;Cancel our timer for sure CancelTimerGameTime() EndIf EndEvent Actor Property AJDBTVaultTecRoboticOperative Auto Holotape Property AJDBTHolotape Auto Actor Property AJDBTEyebotMessenger Auto Const Quest Property AJDBTDialogueController Auto Const Actor Property AJDBTLvlRaider Auto Const Scene Property AJDBTDialogueControllerEyebotScene Auto Const ObjectReference Property AJDBTDiamondCityEntrance Auto Const ObjectReference Property AJDBTDiamondCitySceneStartMarker Auto Const ObjectReference Property AJDBTLogicCellMarker Auto Const ObjectReference Property AJDBTVault111Marker Auto Const Doh! I missed that when I was going over the script. I have added the missing Else for the re-register of the timer and decided for testing's sake to increase the distance from 250 to 1000. The results are not any different. I decided to go a step further and add a Debug message in the OnInit with the message not firing. I have this script attached to a random static inside of a cell that the player will never reach. Are scripts not fired in this scenario for Fallout 4? Edited April 27, 2017 by Arron Dominion Link to comment Share on other sites More sharing options...
Reneer Posted April 27, 2017 Share Posted April 27, 2017 (edited) Doh! I missed that when I was going over the script. I have added the missing Else for the re-register of the timer and decided for testing's sake to increase the distance from 250 to 1000. The results are not any different. I decided to go a step further and add a Debug message in the OnInit with the message not firing. I have this script attached to a random static inside of a cell that the player will never reach. Are scripts not fired in this scenario for Fallout 4?If the player is never within the cell that the static is also in, no, the script / the OnInit will never fire because the object it is attached to is never loaded (unless the reference is marked as persistent). What you seem to be looking for is using this in a Quest script instead of an ObjectReference. Edited April 27, 2017 by Reneer Link to comment Share on other sites More sharing options...
ArronDominion Posted April 28, 2017 Author Share Posted April 28, 2017 I changed the quest containing the scene to a Start Game Enabled Quest, and it has the flags Run Once and Warn On Alias failure enabled. The quest has a single alias for the AJDBTEyebotMessenger NPC, and it is set to UniqueActor | Not Optional | Allow Reuse in Quest In stage 0 of the quest, I have the Run on start? checked, and in the Papyrus Fragment section I have the following call: (AJDBTDialogueController as AJDBTDialogueControllerQuestScript).RegisterGameTime() Here is the quest script that I am using: Scriptname AJDBTDialogueControllerQuestScript extends Quest {This script controls when to start the required scene.} Actor Property AJDBTEyebotMessenger Auto Const Actor Property AJDBTVaultTecOperative Auto Const ObjectReference Property AJDBTVault111Marker Auto Const Actor[] Property AJDBTRaiders Auto Actor Property AJDBTLvlRaider Auto Const ObjectReference Property AJDBTDiamondCityEntrance Auto Const ObjectReference Property AJDBTDiamondCitySceneStartMarker Auto Const Quest Property AJDBTDialogueController Auto Const Quest Property AJDBTQuestForTheVaultTecHomebrew Auto Const Scene Property AJDBTDialogueControllerEyebotScene Auto Const Event OnTimerGameTime(int aiTimerID) ;Ensure that the scene has not been done before if (AJDBTDialogueController.GetStage() < 1) ;Verify the distance Actor Player = Game.GetPlayer() If ((AJDBTDiamondCitySceneStartMarker.GetDistance(Game.GetPlayer()) <= 1000.0)) ;Force first person Game.ForceFirstPerson() ;Disable player controls InputEnableLayer myLayer = InputEnableLayer.Create() myLayer.DisablePlayerControls(true, true, false, true, true, true, true, true, true, true, true) ;Give a notification that controls have been disabled Game.ShakeController(0.75, 0.75, 2) ;Move the eyebot AJDBTEyebotMessenger.Enable() AJDBTEyebotMessenger.MoveTo(AJDBTDiamondCityEntrance) ;Move everything else to kill each other in Vault 111 AJDBTVaultTecOperative.Enable() AJDBTVaultTecOperative.MoveTo(AJDBTVault111Marker) AJDBTLvlRaider.Enable() ;Figure out how many raiders to move to Vault | 2 by default If (Player.GetLevel() < 10) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 2) ElseIf (Player.GetLevel() < 20) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 3) ElseIf (Player.GetLevel() < 30) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 4) ElseIf (Player.GetLevel() < 40) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 5) ElseIf (Player.GetLevel() < 50) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 6) ElseIf (Player.GetLevel() < 60) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 7) Else AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 9) EndIf ;Start the Scene AJDBTDialogueControllerEyebotScene.ForceStart() Else ;Re-register the timer StartTimerGameTime(0.033) EndIf Else EndIf EndEvent Function RegisterGameTime() StartTimerGameTime(0.033) EndFunction Function HandleSceneEnd() ;Re-enable player controls InputEnableLayer myLayer = InputEnableLayer.Create() myLayer.EnablePlayerControls() ;Remove the Eyebot...goodbye dear F.H.A.M.M. AJDBTEyebotMessenger.MoveTo(AJDBTLogicCellMarker) AJDBTEyebotMessenger.Disable() ;Start the quest AJDBTQuestForTheVaultTecHomebrew.Start() AJDBTQuestForTheVaultTecHomebrew.SetStage(10) AJDBTQuestForTheVaultTecHomebrew.SetObjectiveDisplayed(10) EndFunction ObjectReference Property AJDBTLogicCellMarker Auto Const None of the actions contained within the distance segment of the IF...ELSE are firing. Am I screwing something up in setting up the quest, or is there an accepted practice I should be trying instead for setting up a quest with dialogue? Link to comment Share on other sites More sharing options...
Greslin Posted April 28, 2017 Share Posted April 28, 2017 I changed the quest containing the scene to a Start Game Enabled Quest, and it has the flags Run Once and Warn On Alias failure enabled. The quest has a single alias for the AJDBTEyebotMessenger NPC, and it is set to UniqueActor | Not Optional | Allow Reuse in Quest In stage 0 of the quest, I have the Run on start? checked, and in the Papyrus Fragment section I have the following call: (AJDBTDialogueController as AJDBTDialogueControllerQuestScript).RegisterGameTime() Here is the quest script that I am using: Scriptname AJDBTDialogueControllerQuestScript extends Quest {This script controls when to start the required scene.} Actor Property AJDBTEyebotMessenger Auto Const Actor Property AJDBTVaultTecOperative Auto Const ObjectReference Property AJDBTVault111Marker Auto Const Actor[] Property AJDBTRaiders Auto Actor Property AJDBTLvlRaider Auto Const ObjectReference Property AJDBTDiamondCityEntrance Auto Const ObjectReference Property AJDBTDiamondCitySceneStartMarker Auto Const Quest Property AJDBTDialogueController Auto Const Quest Property AJDBTQuestForTheVaultTecHomebrew Auto Const Scene Property AJDBTDialogueControllerEyebotScene Auto Const Event OnTimerGameTime(int aiTimerID) ;Ensure that the scene has not been done before if (AJDBTDialogueController.GetStage() < 1) ;Verify the distance Actor Player = Game.GetPlayer() If ((AJDBTDiamondCitySceneStartMarker.GetDistance(Game.GetPlayer()) <= 1000.0)) ;Force first person Game.ForceFirstPerson() ;Disable player controls InputEnableLayer myLayer = InputEnableLayer.Create() myLayer.DisablePlayerControls(true, true, false, true, true, true, true, true, true, true, true) ;Give a notification that controls have been disabled Game.ShakeController(0.75, 0.75, 2) ;Move the eyebot AJDBTEyebotMessenger.Enable() AJDBTEyebotMessenger.MoveTo(AJDBTDiamondCityEntrance) ;Move everything else to kill each other in Vault 111 AJDBTVaultTecOperative.Enable() AJDBTVaultTecOperative.MoveTo(AJDBTVault111Marker) AJDBTLvlRaider.Enable() ;Figure out how many raiders to move to Vault | 2 by default If (Player.GetLevel() < 10) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 2) ElseIf (Player.GetLevel() < 20) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 3) ElseIf (Player.GetLevel() < 30) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 4) ElseIf (Player.GetLevel() < 40) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 5) ElseIf (Player.GetLevel() < 50) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 6) ElseIf (Player.GetLevel() < 60) AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 7) Else AJDBTVault111Marker.PlaceAtMe(AJDBTLvlRaider, 9) EndIf ;Start the Scene AJDBTDialogueControllerEyebotScene.ForceStart() Else ;Re-register the timer StartTimerGameTime(0.033) EndIf Else EndIf EndEvent Function RegisterGameTime() StartTimerGameTime(0.033) EndFunction Function HandleSceneEnd() ;Re-enable player controls InputEnableLayer myLayer = InputEnableLayer.Create() myLayer.EnablePlayerControls() ;Remove the Eyebot...goodbye dear F.H.A.M.M. AJDBTEyebotMessenger.MoveTo(AJDBTLogicCellMarker) AJDBTEyebotMessenger.Disable() ;Start the quest AJDBTQuestForTheVaultTecHomebrew.Start() AJDBTQuestForTheVaultTecHomebrew.SetStage(10) AJDBTQuestForTheVaultTecHomebrew.SetObjectiveDisplayed(10) EndFunction ObjectReference Property AJDBTLogicCellMarker Auto Const None of the actions contained within the distance segment of the IF...ELSE are firing. Am I screwing something up in setting up the quest, or is there an accepted practice I should be trying instead for setting up a quest with dialogue? Well, I'd say that the next logical step is to see if anything prior to that GetDistance IF call is happening. You basically have three possibilities (other than the script just not running at all): 1. The game timer isn't registering or firing properly. 2. The AJDBTDialogueController quest stage is never 0. 3. Something's up with your marker. Try swapping the values in that IF condition, so that you're comparing "Player.GetDistance(AJDBTDiamondCitySceneStartMarker)" rather than running the GetDistance on the marker. Throw a few debug.notification lines in there and find out exactly which one's the problem. When the messages stop displaying, you know which one it is. Link to comment Share on other sites More sharing options...
Recommended Posts