-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtimer.lua
258 lines (219 loc) · 8.14 KB
/
timer.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
local Timer = {}
DQT.Timer = Timer
-- unique identifier for a quest timer
-- must keep existing enum values to not corrupt saved data
local TIMER_TYPE = {
DUNGEON = 0,
BATTLEGROUNDS = 1,
MOUNT = 2,
BEQUEATHER = 3
}
Timer.TIMER_TYPE = TIMER_TYPE
local DQTName = DQT.Main.name
function Timer:init()
self.questTimers = DQT.SV:getForChar(GetCurrentCharacterId()).questTimers
self:resetDungeonTimer()
self:resetBattlegroundsTimer()
self:resetMountTraining()
self:resetBequeatherTimer()
EVENT_MANAGER:RegisterForEvent(DQTName, EVENT_ACTIVITY_FINDER_ACTIVITY_COMPLETE, Timer.onActivityFinderActivityComplete)
EVENT_MANAGER:RegisterForEvent(DQTName, EVENT_BATTLEGROUND_STATE_CHANGED, Timer.onBattlegroundStateChanged)
EVENT_MANAGER:RegisterForEvent(DQTName, EVENT_RIDING_SKILL_IMPROVEMENT, Timer.onRidingSkillImprovement)
EVENT_MANAGER:RegisterForEvent(DQTName, EVENT_PLAYER_ACTIVATED, Timer.playerActivated)
end
--[[
@param timerType (TIMER_TYPE)
@param cooldown (integer) : timer length, in seconds
--]]
function Timer:resetTimer(timerType, cooldown)
self.questTimers[timerType] = DQT.Utils:getCurrentTime() + cooldown
end
function Timer:resetDungeonTimer()
self:resetTimer(TIMER_TYPE.DUNGEON, GetLFGCooldownTimeRemainingSeconds(LFG_COOLDOWN_DUNGEON_REWARD_GRANTED))
end
function Timer:resetBattlegroundsTimer()
self:resetTimer(TIMER_TYPE.BATTLEGROUNDS, GetLFGCooldownTimeRemainingSeconds(LFG_COOLDOWN_BATTLEGROUND_REWARD_GRANTED))
end
function Timer:resetMountTraining()
if STABLE_MANAGER:IsRidingSkillMaxedOut() then
self.questTimers[TIMER_TYPE.MOUNT] = "na"
else
Timer:resetTimer(TIMER_TYPE.MOUNT, GetTimeUntilCanBeTrained() / 1000)
end
end
function Timer.onRidingSkillImprovement(eventCode, ridingSkillType, previous, current, source)
if source == RIDING_TRAIN_SOURCE_STABLES then
Timer:resetMountTraining()
end
end
function Timer:resetBequeatherTimer(eventCode)
EVENT_MANAGER:UnregisterForEvent(DQTName, EVENT_CHATTER_END)
--Check if Shadowy Supplier passive is purchased, if not set timer to na, else reset timer.
local clientlang = GetCVar("language.2")
if clientlang == "ru" then
if IsSkillAbilityPurchased(5, 6, 4) ~= true then
self.questTimers[TIMER_TYPE.BEQUEATHER] = "na"
else
Timer:resetTimer(TIMER_TYPE.BEQUEATHER, GetTimeToShadowyConnectionsResetInSeconds())
end
elseif clientlang == "en" then
if IsSkillAbilityPurchased(5, 1, 4) ~= true then
self.questTimers[TIMER_TYPE.BEQUEATHER] = "na"
else
Timer:resetTimer(TIMER_TYPE.BEQUEATHER, GetTimeToShadowyConnectionsResetInSeconds())
end
elseif clientlang == "de" then
if IsSkillAbilityPurchased(5, 2, 4) ~= true then
self.questTimers[TIMER_TYPE.BEQUEATHER] = "na"
else
Timer:resetTimer(TIMER_TYPE.BEQUEATHER, GetTimeToShadowyConnectionsResetInSeconds())
end
elseif clientlang == "fr" then
if IsSkillAbilityPurchased(5, 1, 4) ~= true then
self.questTimers[TIMER_TYPE.BEQUEATHER] = "na"
else
Timer:resetTimer(TIMER_TYPE.BEQUEATHER, GetTimeToShadowyConnectionsResetInSeconds())
end
end
end
--[[Use player activated event to determine if in outlaw zone when changing zones for Shadowy Supplier reset
If in outlaw zone regester EVENT_CHATTER_BEGIN to call next function]]
function Timer.playerActivated(eventCode, initial)
if IsInOutlawZone() then
EVENT_MANAGER:RegisterForEvent(DQTName, EVENT_CHATTER_BEGIN, Timer.OnChatterRegister)
else
EVENT_MANAGER:UnregisterForEvent(DQTName, EVENT_CHATTER_BEGIN)
end
end
--[[Check if NPC is Remains-Silent on chatter begin
If so then register EVENT_CHATTER_END to call timer reset when interaction ends]]
function Timer.OnChatterRegister(eventCode, optionCount)
local interactableName = select(2, GetGameCameraInteractableActionInfo())
local RemainsSilent={
["Schweigt-still"]=true,
["Remains-Silent"]=true,
["Хранит-Молчание"]=true,
["Garde-le-Silence"]=true
}
if RemainsSilent[interactableName] then
EVENT_MANAGER:RegisterForEvent(DQTName, EVENT_CHATTER_END, Timer.resetBequeatherTimer)
end
end
--[[
There seems to be a slight delay between when EVENT_ACTIVITY_FINDER_ACTIVITY_COMPLETE fires,
and when GetLFGCooldownTimeRemainingSeconds is actually updated. I have not found a reliable
way to determine if the activity complete was a random dungeon or not, so that we could update
the timer manually. Instead, we try again with a slight delay.
By the time EVENT_ACTIVITY_FINDER_ACTIVITY_COMPLETE fires, GetCurrentLFGActivityId() returns
only the id for this specific dungeon, instead of the id for a random dungeon. Storing the
activity id from when we queued is not reliable because that info could be lost in a disconnect.
--]]
function Timer.onActivityFinderActivityComplete(eventCode)
if ZO_IsActivityTypeDungeon(GetActivityType(GetCurrentLFGActivityId())) then
Timer:resetDungeonTimer()
-- a 1 second delay works for me, but we throw in a few more (with exponential growth) to be safe
local delays = {1, 4, 16}
for _, delay in ipairs(delays) do
zo_callLater(function() Timer:resetDungeonTimer() end, 1000 * delay)
end
end
end
function Timer.onBattlegroundStateChanged(eventCode, previousState, currentState)
--[[
We check for BATTLEGROUND_STATE_POSTGAME instead of
BATTLEGROUND_STATE_FINISHED because this never seems to get called
with BATTLEGROUND_STATE_FINISHED
--]]
if currentState == BATTLEGROUND_STATE_POSTGAME then
-- GetLFGCooldownTimeRemainingSeconds is probably not updated yet, but we try anyway
Timer:resetBattlegroundsTimer()
-- try to reset timer again after they leave the battleground
EVENT_MANAGER:RegisterForEvent(DQTName.."_Battleground_Player_Activated", EVENT_PLAYER_ACTIVATED, Timer.onBattlegroundLeft)
end
end
function Timer.onBattlegroundLeft(eventCode, initial)
EVENT_MANAGER:UnregisterForEvent(DQTName.."_Battleground_Player_Activated", EVENT_PLAYER_ACTIVATED)
Timer:resetBattlegroundsTimer()
end
--[[
@param timeRemaining time remaining in seconds (or nil if unknown, "na" if not applicable)
@return formatted string for display in gui
--]]
function Timer.formatTimeRemaining(timeRemaining)
if timeRemaining == nil then
return "?"
elseif timeRemaining == 0 then
-- color text green if timer is up
return "|c0099000:00|r"
elseif timeRemaining == "na" then
return "-"
else
local hoursRemaining = math.floor(timeRemaining / 3600)
local minutesRemaining = math.floor((timeRemaining - hoursRemaining * 3600) / 60)
return string.format("%d:%.2d", hoursRemaining, minutesRemaining)
end
end
-------- Timer --------
-- boilerplate for class definition
local TimerQuest = ZO_Object.MultiSubclass(DQT.Quest.Quest)
Timer.TimerQuest = TimerQuest
function TimerQuest:new(...)
local object = ZO_Object.New(self)
object:initTimerQuest(...)
return object
end
--[[
This type of "quest" is on a timer based on the last time you completed it.
@param name (string) display name for quest
@param timerType unique TIMER_TYPE identifier
--]]
function TimerQuest:initTimerQuest(name, timerType)
self:init(name)
self._type = timerType
end
-- get time remaining, in seconds, or nil if unknown, or "na" if not applicable
function TimerQuest:getTimeRemaining(characterId)
local resetTime = DQT.SV:getForChar(characterId).questTimers[self._type]
if resetTime == nil then
return nil
elseif resetTime == "na" then
return "na"
end
return math.max(os.difftime(resetTime, DQT.Utils:getCurrentTime()), 0)
end
-- equality operator overload
function TimerQuest.eq(left, right)
return left._type == right._type
end
-------- Timer Section --------
-- boilerplate for class definition
local TimerSection = ZO_Object:Subclass()
Timer.TimerSection = TimerSection
function TimerSection:new(...)
local object = ZO_Object.New(self)
object:init(...)
return object
end
--[[
A timer quest section represents a category of timer quests to group together
@param name (string) a unique section name
@param quests (list) TimerQuest objects
--]]
function TimerSection:init(name, quests)
self._name = name
self._quests = quests
end
function TimerSection:getName()
return self._name
end
function TimerSection:getQuests()
return self._quests
end
-- equality operator overload
function TimerSection.eq(left, right)
return left._name == right._name
end
-- class type
function TimerSection.type()
return "TimerSection"
end