Jump to content

Ceck the inventory of a copanion every x sec or min


ThalonMook

Recommended Posts

Hi all,

 

I need to make a script that check the inventory of a companion in a defined time period.

 

I new with papyrus so I need to know how to start a script on an actor/companion.

 

How to get the comainon I know. Also how to manipulate the inventory.

 

I only need the beginning from scratch plz.

 

Ahh ok I also need to make this switchable. So that I can set the companion check on or off.

I will use MCM for this. How to make a switch with MCM and how to read or write I know.

 

Thx

Thalon

Edited by ThalonMook
Link to comment
Share on other sites

Ok I made a quest 'ThalonCompInventory'.

Set 'Start Game Enabled' disabled 'Run Once'

Then I added a new script:

Scriptname ThalonCheckInventoryScript extends Quest

EVENT onInit()                  ; This event will run once, when the script is initialized
	StartTimer(20)
	gotoState ("waiting")
endEVENT
 
 STATE waiting
	EVENT onTimer(int aiTimerID)			
		Debug.Notification("20 Sekunden Timer abgelaufen!")
	endEVENT
endSTATE

It works an brings a message when the timer is down.

 

Now how I can restart it?

 

*Edit*

Ok I learned that OnInit only runs one time :D

 

Then I need a better way to start the script :unsure:

 

It should be startet with an other script from MCM when I activate the setting. How can I do that?

 

Thx

Thalon

Edited by ThalonMook
Link to comment
Share on other sites

Hi all,

 

can nobody help me with this?

 

I need the timer start from MCM if the switch is enabled but I dont know how to.

 

What I tried atm is following:

ScriptName ThalonCheckInventoryScript extends ScriptObject

EVENT onInit()                  ; This event will run once, when the script is initialized
    int iTimer = MCM.GetModSettingInt("ThalonCompAmmo", "iSliderTime:Main")
    Debug.Notification("Starte Timer " + iTimer + "Min!")
	StartTimer(iTimer*60)
	gotoState ("waiting")
endEVENT
 
STATE waiting
	EVENT onTimer(int aiTimerID)			
		Debug.Notification("Überprüfe Begleiter Munitionsvorat!")
        If (MCM.GetModSettingBool("ThalonCompAmmo", "bEnabledMunCheck:Main"))
            CheckCompMuni()
            int iTimer = MCM.GetModSettingInt("ThalonCompAmmo", "iSliderTime:Main")
            Debug.Notification("Starte Timer " + iTimer + "Min!")
            StartTimer(iTimer*60)
            gotoState ("waiting")
        EndIf
	EndEVENT
EndSTATE

It works as I need but I know if I disable the switch in MCM it will never run again :-(

 

 

Thx Thalon

Edited by ThalonMook
Link to comment
Share on other sites

Hi.

 

As you just discovered, the only way to poll every x seconds is to fire the event again. There are only one-shot timers in Fallout 4.

 

That said, I think you're making it more complicated than it needs to be. You don't REALLY need states for that, you can just register to receive a timer event, and let the game call you when the event comes.

 

In fact, IMHO the only reason why you might need a state anywhere is to PREVENT stuff from happening, not to be notified of it. Like, if you need to trigger something lengthy when the user pulls a lever, and you want to prevent the user from clicking 20 times on it while your script still executes, and starting 20 threads in the process. But if you work with timers that's not necessary, since you can simply not restart the timer until your processing is done.

 

Also, the easiest way to get that running is to extend Quest, not directly the most generic ScriptObject. Just make a new quest, set it to hidden, make sure it can run at start, and just add your script in the last tab.

 

Here's a snip from my weather script

 

int myTimerID = 666 ; Give our timer an ID we can remember

Event OnQuestInit()
	StartTimer(60, myTimerID) ; Create the timer with a 60 second duration
	Debug.Trace("Weather Monitor Initialized")
EndEvent

Event OnTimer(int aiTimerID)		
	If aiTimerID == myTimerID ; The 1 minute timer we started just expired
		CheckWeather()
		StartTimer(60, myTimerID) ; Restart the timer
	EndIf
EndEvent

Well, in your case it would be CheckCompMuni() instead of CheckWeather, but you get the idea.

 

Essentially instead of actively waiting for the event, you just tell the game "hey, call my OnTimer function in a minute" and then end. This, btw, IS saved in the save game. So it will keep ticking. You don't really need to start it more than once.

 

HOWEVER, if I understand your problem correctly, now essentially you want to enable and disable whatever your function CheckCompMuni() does. Probably the easiest is to simply move the StartTimer outside the "If (MCM.GetModSettingBool("ThalonCompAmmo", "bEnabledMunCheck:Main"))" in your script, so it keeps ticking even if the option is disabled.

 

There are other ways, but for now this ought to do.

 

 

You can also do stuff like register to be notified of location changes (character moves across cell boundary), level change, start of combat, all sorts of neat things. I use location changes for example to activate auto-criticals for any companions following me.

 

To do something like that, you'd use something like this:

 

bool registered
Event OnQuestInit()
	If (!registered)
		registered = true
		RegisterForRemoteEvent(Game.GetPlayer(), "OnLocationChange")
		Debug.Trace("Weather monitor: Registered player for location change events.")
	EndIf
EndEvent

Event Actor.OnLocationChange(Actor akSender, Location akOldLoc, Location akNewLoc)
	; watch only for player OnLocationChange events:
	if akSender == Game.GetPlayer()
		CancelTimer(myTimerID)
		CheckCompMuni()
		StartTimer(60, myTimerID) ; Restart the timer
	EndIf
endEvent

Well, or you can do it on your NPC instead of the player. And you probably don't need the if in the quest init unless you let the quest run more than once (in which case, it will run every time the user starts or loads a game), OR if it can be registered from more than one place. Still, if you really need to restart things more than once, that's how you do it.

 

Now, if you don't use timers, you don't need to cancel and start them. BUT I let them in to illustrate a point. If you can start the same timer from more than one place, you may want to cancel it first.

 

Incidentally, CancelTimer is also useful if you want to provide an uninstall option that stops all long running scripts. That way the player can then safely uninstall the mod.

Link to comment
Share on other sites

Hi thx for your help.

 

In the MCM script there is a function that will be fired when a setting ist changed.

I think I can use this to start the timer and maybe stop it.

 

I used the demo script and changed it to my needs.

Scriptname ThalonCompAmmo extends Quest

string Property ThalonComp = "ThalonCompAmmo" AutoReadOnly

Event OnInit()
    RegisterForExternalEvent("OnMCMSettingChange|ThalonCompAmmo", "OnMCMSettingChange")
EndEvent

Function OnMCMSettingChange(string modName, string id)
    ;Debug.Trace("[MCM Quest Script] OnMCMSettingChange modName: " + modName + " id: " + id)
    
    If (modName == ThalonComp)
        If (id == "iSliderAmmo:Main")
            Int newValue = MCM.GetModSettingInt(ThalonComp, "iSliderAmmo:Main")
            MCM.SetModSettingInt(ThalonComp, "iSliderAmmo:Main", newValue)
            ;Debug.Trace("Id: " + id + " Value: " + newValue)
            MCM.RefreshMenu()
        ElseIf (id == "bEnabledMunCheck:Main")
            
            Debug.MessageBox("Mod enabled")
   
        EndIf
    EndIf
    
EndFunction

As you said I want to be sure that the timer will be run only in one script. So that I dont have x timer running.

 

There where the messagebox is called I can start the timer. But I dont how to start it in a seperate script.

Or will this script do other stuff when it waits for the timer is down?

Then I can start the timer here.

 

 

Thx

Thalon

Edited by ThalonMook
Link to comment
Share on other sites

I've never used MCM before, but that sounds like it should do the trick. You can start the timer in OnMCMSettingChange where you have the Debug.MessageBox("Mod enabled"), and then simply have the OnTimer call the check function and restart the timer.

 

Event OnTimer(int aiTimerID)		
	If aiTimerID == myTimerID ; The 1 minute timer we started just expired
		CheckCompMuni()
		StartTimer(60, myTimerID) ; Restart the timer
	EndIf
EndEvent
And basically the script won't really do anything when it's not called. It's just that the game will go on doing whatever it needs to do. Like have raiders shoot at you and whatnot. Then when the clock rings, it will call your event function, so you get to do your stuff too.
Link to comment
Share on other sites

Well, I assume that the enabling ammo check would be a checkbox or such, right? I mean, if there's no way to stop it, it's not much of a setting. You may want to remember its value in a variable in the script. Say a "boolean muniCheckEnabled". Then the example above would be more like:

 

Event OnTimer(int aiTimerID)		
	If aiTimerID == myTimerID && muniCheckEnabled
		CheckCompMuni()
		StartTimer(60, myTimerID) ; Restart the timer
	EndIf
EndEvent
That way, if the ammo check isn't enabled, CheckCompMuni() doesn't get called, and the timer isn't restarted. So basically it doesn't tick endlessly if there is nothing for it to do.
Link to comment
Share on other sites

Ok

 

I did it now this way.

Scriptname ThalonCompAmmo extends Quest

string Property ThalonComp = "ThalonCompAmmo" AutoReadOnly
Int ThalonTimerID = 100


Event OnInit()
    RegisterForExternalEvent("OnMCMSettingChange|ThalonCompAmmo", "OnMCMSettingChange")
EndEvent

Function OnMCMSettingChange(string modName, string id)
    ;Debug.Trace("[MCM Quest Script] OnMCMSettingChange modName: " + modName + " id: " + id)
    
    If (modName == ThalonComp)
        If (id == "iSliderAmmo:Main")
            Int newValue = MCM.GetModSettingInt(ThalonComp, "iSliderAmmo:Main")
            MCM.SetModSettingInt(ThalonComp, "iSliderAmmo:Main", newValue)
            ;Debug.Trace("Id: " + id + " Value: " + newValue)
            MCM.RefreshMenu()
        ElseIf (id == "bEnabledMunCheck:Main")
            int iTimer = MCM.GetModSettingInt("ThalonCompAmmo", "iSliderTime:Main")
            If (MCM.GetModSettingBool("ThalonCompAmmo", "bEnabledMunCheck:Main"))
                CancelTimer(ThalonTimerID)
                Debug.MessageBox("Mod enabled")
                StartTimer(iTimer*60, ThalonTimerID)
            Else
                CancelTimer(ThalonTimerID)
            EndIf
        EndIf
    EndIf
    
EndFunction

EVENT onTimer(int aiTimerID)			
		Debug.Notification("Überprüfe Begleiter Munitionsvorat!")
        If (MCM.GetModSettingBool("ThalonCompAmmo", "bEnabledMunCheck:Main"))
            CheckCompMuni()
            int iTimer = MCM.GetModSettingInt("ThalonCompAmmo", "iSliderTime:Main")
            Debug.Notification("Starte Timer " + iTimer + "Min!")
            StartTimer(iTimer*60, ThalonTimerID)
        EndIf
EndEVENT

Function CheckCompMuni()
blub blub blub do your thing
EndFunction

It compiled so I think it will work :D

 

The bEnabledMunCheck:Main is a switch so if it's enabled the value ist true and if disabled it's false.

The iSliderTime:Main is a slider that will give the timer length.

 

If the switch is of the timer should be stoped

 

Thx

Thalon

Edited by ThalonMook
Link to comment
Share on other sites

  • Recently Browsing   0 members

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