Jump to content

Creating Background Heartbeat-Like Script


MegaStorm

Recommended Posts

So back for Fallout 3, I wrote this extensive F3SE-based mod. (I actually only used F3SE to capture keyboard input, i.e., to create myself some hotkeys.)

 

With that version of the Fallout engine, things were easy in that you only needed to create a quest, attach a script to it, and then stick your stuff in a Begin/End block and use SetQuestDelay to get it to be continuously called by the engine:

 

ScriptName GuardianScript

int bInitialized ;flags whether or not to initialize variables
ref myJunkLocker ;ref to locker by door in my Megaton house

Begin GameMode
;;---------------------------------------
;; Initialization Block
;;---------------------------------------
if( bInitialized == 0 )
SetQuestDelay GuardianScriptQuest 0.1 ;run every 100 ms

Set bInitialized to 1

Set myJunkLocker to DefaultMLocker02 ;locker at Megaton house (closest to door)

return
endif


;; other stuff

End

How do you accomplish something similar with the new engine? I've followed the various simplistic "Hello World" examples that create a quest and attach a script to that quest, but the problem with every single one of those tutorials is they don't bother to mention that the script will only run once and never again. :confused: OnQuestInit, OnReset, and even OnStageSet are never called after the very first time you load a save.

 

So with the new event-driven engine, what's the best way to get a Quest script to run at a regular interval?

 

 

Link to comment
Share on other sites

Okay, so I stuck a StartTimer() function in my OnQuestInit(), and that seems to persist between game sessions, but that seems kind of cheesy.

 

So to reiterate my above query, what exactly is the Fallout 4 equivalent to Fallout 3's 'Begin GameMode' block? I mean, once the player has a quest, the game engine needs to execute some script at some regular interval if only just to see if the conditions have been met to advance to the next Quest stage. In Fallout 3, as I stated above, that was accomplished via the SetQuestDelay command, and the same attached quest script was continuously executed. How is that done in Fallout 4?

Edited by MegaStorm
Link to comment
Share on other sites

As its event driven, try to find status change or action events to register your script for notifications on, most of 'em on one page here.

 

If none of them work then your timer is fine and should keep ticking between saves ... although .... I always add an OnPlayerLoadGame() StartTimer() to ensure timers do keep ticking between saves (needs to be in a script attached to a Quest alias forced to the player).

Link to comment
Share on other sites

As its event driven, try to find status change or action events to register your script for notifications on, most of 'em on one page here.

 

If none of them work then your timer is fine and should keep ticking between saves ... although .... I always add an OnPlayerLoadGame() StartTimer() to ensure timers do keep ticking between saves (needs to be in a script attached to a Quest alias forced to the player).

 

I tried the OnPlayerLoadGame() because that's something I need desperately (since OnQuestInit() is only called once per new save), but I get a compile error stating that the script needs to be native:

C:\Users\Neutrino\AppData\Local\Temp\PapyrusTemp\Neutrino\MainScript.psc(70,0): new event onplayerloadgame cannot be defined because the script is not flagged as native

And making the script native isn't an option, I don't believe, because I get a lot more errors if I try that. :ohmy:

 

ETA: I suppose to elaborate more, I can't make my script Native because then I have no way (that I know of) of defining my 'global' variables. (Some things I need to keep global like my timer IDs, custom formlist references, etc.)

 

ETA #2: Baby steps, I suppose. I created a Quest Alias (and within, a reference alias to 'Player'), and then I attached a script to that. In that script, I have both OnInit() and OnPlayerLoadGame() event handlers defined, but only OnInit() ever gets called. (It's called every time I load a game.) Heh, I suppose I can be very hacky-ish and just use that script as my entry point and ditch the script quest altogether. Nope, never mind. Like OnQuestInit(), OnInit() is getting called once and only once. Once I save the game and then reload, it doesn't get called.

Edited by MegaStorm
Link to comment
Share on other sites

What's your ultimate goal here? Add a constant heartbeat to the player? Only during combat? States might be of use to you here. You can have your script enter different states based on some events. So say you had 2 states, IdleState and ActionState. In your idle state you do nothing , in your action state you could run a loop to a play a sound. Then we'd need to work out the best way to loop the sound at different speeds. Maybe based on some quick checks to the player that can change the timer value that would be used to delay the sound. Maybe use different sound files that have different speeds and do the same (I think the checks would be slower and less desirable for this purpose though)

 

https://www.creationkit.com/index.php?title=States_(Papyrus)

Link to comment
Share on other sites

@SKK50, Are you sure your OnPlayerLoadGame() event handler is being called like you think it is? I can't get it to work. I followed the wiki's sample code to the letter, but it's never being called.

 

Reference: https://www.creationkit.com/index.php?title=Complete_Example_Scripts#Maintenance.2Fupdate_code_which_runs_once_per_save_load_and_shows_a_message_when_a_mod_is_updated_or_first_loaded

 

On a fresh save, I getting the following:

[12/13/2017 - 06:05:22PM] [Neutrino]  OnInit()
[12/13/2017 - 06:05:23PM] [Neutrino]     OnGameStart()
[12/13/2017 - 06:05:23PM] [Neutrino]  OnQuestInit()
[12/13/2017 - 06:05:23PM] [Neutrino]     OnGameStart()
[12/13/2017 - 06:05:23PM] [Neutrino]  OnReset()
[12/13/2017 - 06:05:23PM] [Neutrino]  OnInit()
[12/13/2017 - 06:05:23PM] [Neutrino]     OnGameStart()

(OnGameStart() is my renaming of the wiki's Maintenance() example.)

 

If I then save and reload, I get no events at all.

 

 

@SMB92,

 

It's kind of like a utility/maintenance script I like to have running in the background. I had a lot of fun with it in Fallout 3. Sort a minor cheat script, but more of a tedium removal tool. With F3SE, I would create hotkeys to do things like sell certain junk items, ammo, and weapons (using custom form lists), give and equip targets with specific armor, etc. Cheat-aspect is I would monitor my ammo and/or caps to make sure that they did not go below a certain level. Also, adjust the weight of my current items. (Super trivial via script as opposed to permanently replacing the all items in the game.) Things like that.

 

At this stage, though, I'm just trying to figure out how to hook into the game reliably. There has to be a way. By reliable, I mean I need to have a means to know when a game is loaded, and I'm trying to avoid doing things like creating a dummy cell with a dummy static object and then attach to that dummy object. It'd work, I suppose, but there has to be a way to do this via a quest script I would think.

Link to comment
Share on other sites

I'm not at the CK, so this is only a guess. You might have to RegisterForRemoteEvent(Player, "OnPlayerLoadGame").

 

The event exists and is being sent to actor according to the wiki, so it's just a matter of listening in the right place.

 

https://www.creationkit.com/fallout4/index.php?title=RegisterForRemoteEvent_-_ScriptObject

Link to comment
Share on other sites

Seems I'm off with the fairies in thinking you were making a sound mod :) Still not a bad idea though :D

 

It's not considered good practice I think, but you could try putting the player in alias with a script. Then you could attach a script extending Actor and get events directly. Suppose you could attach a magic effect as well as an alternative. Otherwise maybe the remote events could work for your purposes.

Link to comment
Share on other sites

A personal butler script is a nice idea. Having somebody/thing check your well being every X interval is first class. The ultimate custom experience ^_^

 

Btw MegaStorm were you a MUD programmer? Timers in "livings" were called heartbeats. Haven't heard that in awhile.

Link to comment
Share on other sites

I'm not at the CK, so this is only a guess. You might have to RegisterForRemoteEvent(Player, "OnPlayerLoadGame").

 

The event exists and is being sent to actor according to the wiki, so it's just a matter of listening in the right place.

 

https://www.creationkit.com/fallout4/index.php?title=RegisterForRemoteEvent_-_ScriptObject

 

Sounds like a good idea, but it's a catch-22. So following that wiki, it turns out that the YourPlayerAliasScript is not being invoked at all. The OnInit() in my trace is strictly from my main quest script. So I could register for the event, but I have no where to put the handler.

 

This might be related to SMB's suggestion (below), and I'm doing something wrong.

 

 

 

Seems I'm off with the fairies in thinking you were making a sound mod :smile: Still not a bad idea though :D

 

It's not considered good practice I think, but you could try putting the player in alias with a script. Then you could attach a script extending Actor and get events directly. Suppose you could attach a magic effect as well as an alternative. Otherwise maybe the remote events could work for your purposes.

 

So the "try putting the player in alias with a script" part... specifically, how does one do that? I'm still a little fuzzy on this new aliasing aspect of the engine.

 

Is it as simple as adding...

Player property PlayerRef auto

...one's script, or do I do it via a property box or something in the creation kit?

Link to comment
Share on other sites

  • Recently Browsing   0 members

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