iqoniq Posted June 11, 2023 Share Posted June 11, 2023 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 More sharing options...
Fantafaust Posted June 11, 2023 Share Posted June 11, 2023 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 More sharing options...
SKKmods Posted June 11, 2023 Share Posted June 11, 2023 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 More sharing options...
Fantafaust Posted June 11, 2023 Share Posted June 11, 2023 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 More sharing options...
iqoniq Posted June 11, 2023 Author Share Posted June 11, 2023 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 More sharing options...
Fantafaust Posted June 12, 2023 Share Posted June 12, 2023 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 More sharing options...
lee3310 Posted June 13, 2023 Share Posted June 13, 2023 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 More sharing options...
SKKmods Posted June 13, 2023 Share Posted June 13, 2023 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 More sharing options...
dylbill Posted June 13, 2023 Share Posted June 13, 2023 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 More sharing options...
Recommended Posts