Jump to content

Any way to detect how long is left on a timer?


iqoniq

Recommended Posts

Is there any way that I can detect how long is left on a timer. I want to be able to manipulate it to extend and shorten the timer. At the moment I've got a global I'm updating by setting a timer for 1 or 5 seconds which subtracts 1 from a global and then resets the timer, or fails the quest if zero. If an event happens it just adds or subtracts from the golbal.

 

At the moment it means I'm running two quests (the actual quest and the timer quest, and the two interact), but I'd prefer to be be able to see how long the timer has left at the point needed, and then stop and restart the timer with the modified value. It's also not tying Papyrus up needlessly (if it's possible anyway) as there's quite a lot going on in the background. Is it possible?

Link to comment
Share on other sites

Define "modified value" in this context. Do you mean you want to ADD a certain amount to the timer, or you want to reset the timer to 5?

If it's the first one I think you could probably use Utility.GetCurrentGameTime() when you start the timer, and also when you run your function, compare the two and add the difference when starting the timer again.

 

If it's the second one(5 seconds reset) you just run the same timer id at 5 seconds and it resets.

Link to comment
Share on other sites

Only if you store an ETA and then subtract current time from that. Then cancel and restart the timer.

 

BUT WARNINGS ...

 

(a) StartTimerGameTime() and GetCurrentGameTime() in GameHours are paused in menus, but values are preserved across OnPlayerLoadGame.

 

(b) StartTimer() in real seconds do not tick in menus. To maintain a realtime ETA have to store an end time and reset the timer at each OnMenuOpenCloseEvent (abOpening == false) event and use Utility.IsMenuMode to detect multipe stacked open menus e.g. (PipboyMenu + PauseMenu).

© GetCurrentRealTime() in real seconds do still tick in menus BUT is reset to zero OnPlayerLoadGame so to maintain a reltime ETA you have to also store a GameTime based ETA and then factor back from that at the current Timescale every OnPlayerLoadGame.

Link to comment
Share on other sites

SKK50 is right, but I assumed this was an in-game timer, ie the player has 5 seconds to hit a button or else the bad stuff happens, and you would still want the player to be able to pause the game(presumably)

 

So it depends on your needs.

Link to comment
Share on other sites

It's a kind of escape room/maze (which can change the solution mid level, so you may go in one room and come out another) scenario I'm working on , but it's split over several "levels". The player needs to complete the levels in a global set time period which is real world time not game time, so they could take 3 minutes on one level, 5, minutes on the next, and then until the time ran out on the next level. The levels also aren't forced on the player, so when one level is completed the player can leave and go and do something else, then do the next level later on. I don't want the player feeling like they're "locked in" for the duration. As they progress through the levels they'll meet enemies which when killed drop power ups, some of which will add time when picked up. The only way I could see doing it was dividing the time needed by the update period and then adding (or possibly removing) it to the global value.

 

Thinking about it, it could possibly cause more problems because I'd need to halt the timer, work out all the new values, and then start the timer again with the new ones. I'll need to do some research and see if I can figure it out.

 

Thanks for the help :)

Link to comment
Share on other sites

Hmm. You could make a global variable increment every second the timer is going and then stop it when they do the thing using that value for the next timer, then starting another fresh increment and timer etc.

 

ie the player has three things to do, 20 seconds each.

During the 20 seconds to do the first thing, if they do it in 14, you set the second timer to 20+(20-14)

but the second task took them longer, 30 seconds, so the third timer is set to 20+(26-30)

They only have 16 seconds to do the third task or they fail entirely.

 

 

Or something like that, anyways.

Link to comment
Share on other sites

Only if you store an ETA and then subtract current time from that. Then cancel and restart the timer.

 

BUT WARNINGS ...

 

(a) StartTimerGameTime() and GetCurrentGameTime() in GameHours are paused in menus, but values are preserved across OnPlayerLoadGame.

 

(b) StartTimer() in real seconds do not tick in menus. To maintain a realtime ETA have to store an end time and reset the timer at each OnMenuOpenCloseEvent (abOpening == false) event and use Utility.IsMenuMode to detect multipe stacked open menus e.g. (PipboyMenu + PauseMenu).

© GetCurrentRealTime() in real seconds do still tick in menus BUT is reset to zero OnPlayerLoadGame so to maintain a reltime ETA you have to also store a GameTime based ETA and then factor back from that at the current Timescale every OnPlayerLoadGame.

Does StartTimer() stops when any menu is opened (pipboy, barter,container, console...) or just pause menu (ESC).

Link to comment
Share on other sites

StartTimer() in real seconds pauses in any UI menu, so every menu event needs to be registered for accurate ETAs:

 

 

 


;********************************************************************************************************************

Function RegisterMenuEvents()

If (bMenuEventsRegistered == False) ;because multiple call paths to enable/disable
	bMenuEventsRegistered  = True

	Self.RegisterForMenuOpenCloseEvent("BarterMenu")
	Self.RegisterForMenuOpenCloseEvent("BookMenu")
	Self.RegisterForMenuOpenCloseEvent("Console")
	Self.RegisterForMenuOpenCloseEvent("ConsoleNativeUIMenu")
	Self.RegisterForMenuOpenCloseEvent("ContainerMenu")
	Self.RegisterForMenuOpenCloseEvent("CookingMenu")
	Self.RegisterForMenuOpenCloseEvent("CreditsMenu")
	;Self.RegisterForMenuOpenCloseEvent("CursorMenu") ;duplicates pipboymenu
	Self.RegisterForMenuOpenCloseEvent("DialogueMenu")
	Self.RegisterForMenuOpenCloseEvent("ExamineMenu")
	;Self.RegisterForMenuOpenCloseEvent("FaderMenu")
	Self.RegisterForMenuOpenCloseEvent("FavoritesMenu")
	Self.RegisterForMenuOpenCloseEvent("GenericMenu")
	Self.RegisterForMenuOpenCloseEvent("HUDMenu")
	Self.RegisterForMenuOpenCloseEvent("LevelUpMenu")
	Self.RegisterForMenuOpenCloseEvent("LoadingMenu")
	Self.RegisterForMenuOpenCloseEvent("LockpickingMenu")
	Self.RegisterForMenuOpenCloseEvent("LooksMenu")
	Self.RegisterForMenuOpenCloseEvent("MainMenu")
	Self.RegisterForMenuOpenCloseEvent("MessageBoxMenu")
	Self.RegisterForMenuOpenCloseEvent("MultiActivateMenu")
	Self.RegisterForMenuOpenCloseEvent("PauseMenu")
	Self.RegisterForMenuOpenCloseEvent("PipboyMenu")
	Self.RegisterForMenuOpenCloseEvent("PromptMenu")
	Self.RegisterForMenuOpenCloseEvent("ScopeMenu")
	Self.RegisterForMenuOpenCloseEvent("SitWaitMenu")
	Self.RegisterForMenuOpenCloseEvent("SleepWaitMenu")
	Self.RegisterForMenuOpenCloseEvent("SPECIALMenu")
	Self.RegisterForMenuOpenCloseEvent("TerminalHolotapeMenu")
	Self.RegisterForMenuOpenCloseEvent("TerminalMenu")
	Self.RegisterForMenuOpenCloseEvent("VATSMenu")
	;Self.RegisterForMenuOpenCloseEvent("VignetteMenu") ;DUPLICATES LOCKPICK
	Self.RegisterForMenuOpenCloseEvent("WorkshopMenu")
	Self.RegisterForMenuOpenCloseEvent("Workshop_CaravanMenu")
EndIf

EndFunction

;********************************************************************************************************************

 

 

Link to comment
Share on other sites

Unfortunately I don't think you can do it without updating every second as FantaFaust said. I would just use 1 second increments for the timer, and keep track of how many seconds have passed with an int variable. Something like this:

 

Scriptname TM_QuestScript extends Quest 

Int Property TimerCount = 0 Auto 
Int Property TimerID = 1 Auto

Event OnInit() 
    StartTimer(1, TimerID)
EndEvent

Event OnTimer(int aiTimerID)        
    If aiTimerID == TimerID
        TimerCount += 1
        If TimerCount == 5 
            ;Objective Failed, do something. 
        Else 
            StartTimer(1, TimerID)
        Endif
    Endif 
EndEvent
Then for your powerup in another script you can do:
Scriptname TM_ReferenceAliasScript extends ReferenceAlias 
;alias pointing to the player

TM_QuestScript Property QuestScriptRef Auto
MiscObject Property PowerUp Auto

Event OnInit()
    AddInventoryEventFilter(PowerUp)
Endevent 

Event OnItemAdded(Form akBaseItem, Int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
    If akBaseItem == PowerUp
        QuestScriptRef.TimerCount -= 1 ;remove 1 from timer count, giving more time. 
    Endif
EndEvent
Link to comment
Share on other sites

  • Recently Browsing   0 members

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