crimewatchTimers.py (29638B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\crimewatch\crimewatchTimers.py 2 import collections 3 import logging 4 from math import pi 5 import enum 6 import gametime 7 import trinity 8 import uthread 9 import uthread2 10 from abyss.common.constants import DEFAULT_ABYSS_CONTENT_DURATION 11 from carbon.common.lib.const import HOUR, SEC 12 from carbonui import uiconst 13 from carbonui.primitives.container import Container 14 from carbonui.primitives.sprite import Sprite 15 from carbonui.primitives.transform import Transform 16 from carbonui.uicore import uicore 17 from carbonui.util.color import Color 18 from datetimeutils import datetime_to_filetime 19 from eve.client.script.ui import eveColor 20 from eve.client.script.ui.control import eveLabel 21 from eve.client.script.ui.control.gaugeCircular import GaugeCircular 22 from eve.client.script.ui.crimewatch.crimewatchConst import Colors 23 from eve.client.script.ui.crimewatch.crimewatchHints import TimerHint, EngagementTimerHint, BoosterTimerHint, JumpTimerHint, JumpTimerFatigueHint, EmanationLockHint 24 from eve.client.script.ui.shared.neocom.corporation.war.atWarIcon import AtWarCont 25 from eve.common.lib import appConst as const 26 from localization import GetByLabel 27 from pvpFilaments.common.constants import DEFAULT_PVP_CONTENT_DURATION 28 from stargate.client import get_gate_lock_messenger 29 from stargate.client.gateLockController import GateLockController 30 from uihider import UiHiderMixin 31 from uihighlighting import uniqueNameConst, UiHighlightDirections 32 from stargate.client.const import GATE_LOCK_MAX_TIMER_TIME, SETTINGS_FIRST_HIGHLIGHT_SHOWN 33 from voidspace.common.constants import VOID_SPACE_ENCOUNTER_LIFE_TIME 34 logger = logging.getLogger(__name__) 35 ALPHA_EMPTY = 0.2 36 BLINK_BEFORE_DONE_TIME = SEC * 5 37 TimerData = collections.namedtuple('TimerData', ['icon', 38 'smallIcon', 39 'color', 40 'tooltip', 41 'maxTimeout', 42 'resetAudioEvent', 43 'endingAudioEvent', 44 'timerFunc', 45 'hintClass', 46 'callbackName', 47 'timerAttributeName']) 48 49 class TimerType(enum.IntEnum): 50 Weapons = 0 51 Npc = 1 52 Pvp = 2 53 Suspect = 3 54 Criminal = 4 55 Engagement = 5 56 Booster = 6 57 JumpActivation = 7 58 JumpFatigue = 8 59 JumpCloak = 9 60 Invulnerable = 10 61 AbyssalContentExpiration = 11 62 AbyssalPvpExpiration = 14 63 VoidSpaceContentExpiration = 16 64 Disapproval = 17 65 EmanationLock = 18 66 67 68 CRIMEWATCH_TIMER_DATA = {TimerType.Disapproval: TimerData('res:/UI/Texture/Crimewatch/Crimewatch_Disapproval.png', 'res:/UI/Texture/Crimewatch/Crimewatch_Disapproval_Small.png', Colors.Disapproval.GetRGBA(), 'UI/Crimewatch/Timers/DisapprovalTimerTooltip', const.disapprovalTimerTimeout, 'crimewatch_weapons_timer_play', 'crimewatch_weapons_timer_end_play', gametime.GetSimTime, None, None, 'disapprovalTimer'), 69 TimerType.Weapons: TimerData('res:/UI/Texture/Crimewatch/Crimewatch_Locked.png', 'res:/UI/Texture/Crimewatch/Crimewatch_Locked_Small.png', Colors.Red.GetRGBA(), 'UI/Crimewatch/Timers/WeaponsTimerTooltip', const.weaponsTimerTimeout, 'crimewatch_weapons_timer_play', 'crimewatch_weapons_timer_end_play', gametime.GetSimTime, None, None, 'weaponsTimer'), 70 TimerType.Npc: TimerData('res:/UI/Texture/Crimewatch/Crimewatch_Combat.png', 'res:/UI/Texture/Crimewatch/Crimewatch_Combat_Small.png', Colors.Yellow.GetRGBA(), 'UI/Crimewatch/Timers/PveTimerTooltip', const.npcTimerTimeout, 'crimewatch_log_off_timer_new_play', 'crimewatch_log_off_timer_end_play', gametime.GetSimTime, None, None, 'npcTimer'), 71 TimerType.Pvp: TimerData('res:/UI/Texture/Crimewatch/Crimewatch_Combat.png', 'res:/UI/Texture/Crimewatch/Crimewatch_Combat_Small.png', Colors.Red.GetRGBA(), 'UI/Crimewatch/Timers/PvpTimerTooltiip', const.pvpTimerTimeout, 'crimewatch_log_off_timer_new_play', 'crimewatch_log_off_timer_end_play', gametime.GetSimTime, None, None, 'pvpTimer'), 72 TimerType.Suspect: TimerData('res:/UI/Texture/Crimewatch/Crimewatch_SuspectCriminal.png', 'res:/UI/Texture/Crimewatch/Crimewatch_SuspectCriminal_Small.png', Colors.Suspect.GetRGBA(), 'UI/Crimewatch/Timers/SuspectTimerTooltip', const.criminalTimerTimeout, 'crimewatch_criminal_timer_play', 'crimewatch_criminal_timer_end_play', gametime.GetSimTime, None, None, 'criminalTimer'), 73 TimerType.Criminal: TimerData('res:/UI/Texture/Crimewatch/Crimewatch_SuspectCriminal.png', 'res:/UI/Texture/Crimewatch/Crimewatch_SuspectCriminal_Small.png', Colors.Criminal.GetRGBA(), 'UI/Crimewatch/Timers/CriminalTimerTooltip', const.criminalTimerTimeout, 'crimewatch_criminal_timer_play', 'crimewatch_criminal_timer_end_play', gametime.GetSimTime, None, None, 'criminalTimer'), 74 TimerType.Engagement: TimerData('res:/UI/Texture/Crimewatch/Crimewatch_LimitedEngagement.png', None, Colors.Engagement.GetRGBA(), None, const.crimewatchEngagementDuration, 'crimewatch_engagement_timer_play', 'crimewatch_engagement_timer_end_play', gametime.GetWallclockTime, EngagementTimerHint, None, 'engagementTimer'), 75 TimerType.Booster: TimerData('res:/UI/Texture/Crimewatch/booster.png', None, Colors.Boosters.GetRGBA(), None, const.crimewatchEngagementDuration, 'boostertimer_timerstart_play', 'boostertimer_timerend_play', gametime.GetWallclockTime, BoosterTimerHint, None, 'boosterTimer'), 76 TimerType.JumpActivation: TimerData('res:/UI/Texture/Crimewatch/Crimewatch_JumpActivation.png', None, (0.945, 77 0.353, 78 0.141, 79 1.0), 'UI/Crimewatch/Timers/JumpActivationTooltip', 1, 'jump_activation_timer_play', 'jump_activation_timer_end_play', gametime.GetWallclockTime, JumpTimerHint, 'DeleteWhenFinished', 'jumpActivationTimer'), 80 TimerType.JumpFatigue: TimerData('res:/UI/Texture/Crimewatch/Crimewatch_JumpFatigue.png', None, (0.0, 81 1.0, 82 1.0, 83 1.0), 'UI/Crimewatch/Timers/JumpFatigueTooltip', 1, 'jump_fatigue_timer_play', 'jump_fatigue_timer_end_play', gametime.GetWallclockTime, JumpTimerFatigueHint, 'DeleteWhenFinished', 'jumpFatigueTimer'), 84 TimerType.JumpCloak: TimerData('res:/UI/Texture/Crimewatch/jump_cloak.png', None, (0.0, 85 1.0, 86 1.0, 87 1.0), 'UI/Crimewatch/Timers/JumpCloakTooltip', 1, None, None, gametime.GetSimTime, None, 'DeleteWhenFinished', 'jumpCloakTimer'), 88 TimerType.Invulnerable: TimerData('res:/UI/Texture/Crimewatch/invulnerable.png', None, (0.0, 89 1.0, 90 1.0, 91 1.0), 'UI/Crimewatch/Timers/InvulTooltip', 1, None, None, gametime.GetSimTime, None, 'DeleteWhenFinished', 'invulnTimer'), 92 TimerType.AbyssalContentExpiration: TimerData('res:/UI/Texture/crimewatch/deadspace.png', None, Colors.Red.GetRGBA(), 'UI/Crimewatch/Timers/AbyssalContentExpiryTooltip', DEFAULT_ABYSS_CONTENT_DURATION, None, None, gametime.GetSimTime, None, 'DeleteWhenFinished', 'abyssalContentExpirationTimer'), 93 TimerType.AbyssalPvpExpiration: TimerData('res:/UI/Texture/crimewatch/deadspace.png', None, (0.541, 94 0.169, 95 0.886, 96 1.0), 'UI/Crimewatch/Timers/AbyssalContentExpiryTooltip', DEFAULT_PVP_CONTENT_DURATION, None, None, gametime.GetSimTime, None, 'DeleteWhenFinished', 'abyssalContentExpirationTimer'), 97 TimerType.VoidSpaceContentExpiration: TimerData('res:/UI/Texture/crimewatch/deadspace.png', None, Colors.Red.GetRGBA(), 'UI/Crimewatch/Timers/voidSpaceContentExpiryTooltip', VOID_SPACE_ENCOUNTER_LIFE_TIME, None, None, gametime.GetSimTime, None, 'DeleteWhenFinished', 'voidSpaceContentExpirationTimer'), 98 TimerType.EmanationLock: TimerData('res:/UI/Texture/eveicon/system_icons/link_16px.png', None, Colors.Yellow.GetRGBA(), 'UI/Crimewatch/Timers/EmanationLockTimerTooltip', GATE_LOCK_MAX_TIMER_TIME, None, None, gametime.GetWallclockTime, EmanationLockHint, 'DeleteWhenFinished', 'emanationLockTimer')} 99 100 class Timer(Container): 101 default_width = 46 102 default_align = uiconst.TOLEFT 103 default_hintClass = TimerHint 104 105 def ApplyAttributes(self, attributes): 106 Container.ApplyAttributes(self, attributes) 107 timerData = CRIMEWATCH_TIMER_DATA[attributes.Get('timerType')] 108 self.hintClass = timerData.hintClass or self.default_hintClass 109 self.state = uiconst.UI_PICKCHILDREN 110 self.timerHint = None 111 self.showHint = False 112 self.expiryTime = None 113 self.iconBlink = None 114 self.rewind = False 115 self.ratio = 0.0 116 self.counterText = None 117 self.animationThread = None 118 self.timerType = attributes.Get('timerType') 119 self.timerData = attributes.get('timerData', timerData) 120 self.GetTime = self.timerData.timerFunc 121 self.activeAnimationCurves = None 122 self.callback = attributes.get('callback', None) 123 self.updateTimestamp = None 124 self.customData = None 125 self.content = Transform(parent=self, name='content', align=uiconst.TOPLEFT, pos=(0, 0, 32, 32), state=uiconst.UI_NORMAL) 126 self.content.OnMouseEnter = self.OnMouseEnter 127 self.iconTransform = Transform(parent=self.content, name='iconTransform', align=uiconst.CENTER, width=16, height=16, state=uiconst.UI_DISABLED) 128 self.icon = Sprite(name='icon', parent=self.iconTransform, pos=(0, 0, 16, 16), texturePath=self.timerData.icon, color=self.timerData.color, state=uiconst.UI_DISABLED, align=uiconst.CENTER) 129 self.gaugeCircular = GaugeCircular(parent=self.content, radius=16, align=uiconst.CENTER, colorStart=self.timerData.color, colorEnd=self.timerData.color, colorBg=self._GetGaugeBgColor(self.timerData.color), lineWidth=2.5, clockwise=False, showMarker=False, state=uiconst.UI_DISABLED) 130 self.pointerContainer = Transform(name='pointer_container', parent=self.content, width=32, height=32, idx=0) 131 self.pointerClipper = Container(parent=self.pointerContainer, pos=(9, -10, 15, 13), clipChildren=True, align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED) 132 self.pointerSprite = Sprite(name='cycle_pointer', parent=self.pointerClipper, pos=(0, 0, 15, 19), texturePath='res:/UI/Texture/Crimewatch/Crimewatch_TimerPoint_WithShadow.png', color=self.timerData.color, align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED) 133 self.iconTransform.scalingCenter = (0.5, 0.5) 134 uicore.animations.Tr2DScaleTo(self.iconTransform, startScale=(0.8, 0.8), endScale=(1.0, 1.0), duration=0.75, curveType=uiconst.ANIM_OVERSHOT) 135 136 def _GetGaugeBgColor(self, color): 137 return Color(*color).SetAlpha(ALPHA_EMPTY).GetRGBA() 138 139 def SetTimerType(self, timerType): 140 self.timerData = CRIMEWATCH_TIMER_DATA[timerType] 141 r, g, b, a = self.timerData.color 142 self.icon.SetRGBA(r, g, b, a) 143 self.pointerSprite.SetRGBA(r, g, b, a) 144 self.gaugeCircular.SetColor(self.timerData.color, self.timerData.color) 145 self.gaugeCircular.SetColorBg(self._GetGaugeBgColor(self.timerData.color)) 146 self.timerType = timerType 147 148 def SetRatio(self, ratio): 149 self.ratio = min(1.0, max(0.0, ratio)) 150 rotation = min(pi * 2, 2 * pi * self.ratio) 151 self.pointerContainer.rotation = rotation 152 self.gaugeCircular.SetValue(ratio, animate=False) 153 154 def SetExpiryTime(self, expiryTime, doAlert, maxDuration = None, updateTimestamp = None): 155 logger.debug('Setting timer %s expiry time to %s', self.name, expiryTime) 156 self.Reset(expiryTime, doAlert, maxDuration=maxDuration) 157 self.expiryTime = expiryTime 158 self.updateTimestamp = updateTimestamp 159 if expiryTime is None: 160 self.PlayActiveAnimation() 161 else: 162 self.animationThread = uthread.new(self.Animate_Thread) 163 164 def Reset(self, resetTo, doAlert, maxDuration = None): 165 if self.animationThread is not None: 166 self.animationThread.kill() 167 if maxDuration and maxDuration != self.timerData.maxTimeout: 168 self.timerData = self.timerData._replace(maxTimeout=maxDuration) 169 uthread.new(self.Rewind_Thread, resetTo, doAlert) 170 171 def Rewind_Thread(self, resetTo, doAlert): 172 if self.rewind: 173 return 174 if doAlert and self.timerData.resetAudioEvent is not None: 175 sm.GetService('audio').SendUIEvent(self.timerData.resetAudioEvent) 176 self.rewind = True 177 ratio = self.ratio 178 startTime = self.GetTime() 179 distance = 1 - ratio 180 cycleSpeed = float(distance * 500) 181 while not self.destroyed and self.ratio < (self.GetRatio(resetTo - self.GetTime()) if resetTo is not None else 1.0): 182 elapsedTime = gametime.GetTimeDiffInMs(startTime, self.GetTime()) 183 toAdd = elapsedTime / cycleSpeed 184 self.SetRatio(ratio + toAdd) 185 uthread2.sleep(0.025) 186 187 self.rewind = False 188 189 def FlipFlop(self, sprite, duration = 1.0, startValue = 0.0, endValue = 1.0, loops = 5): 190 curve = trinity.Tr2CurveScalar() 191 curve.AddKey(0, startValue, trinity.Tr2CurveInterpolation.LINEAR) 192 curve.AddKey(0.01 * duration, endValue, trinity.Tr2CurveInterpolation.LINEAR) 193 curve.AddKey(0.5 * duration, endValue, trinity.Tr2CurveInterpolation.LINEAR) 194 curve.AddKey(0.51 * duration, startValue, trinity.Tr2CurveInterpolation.LINEAR) 195 curve.AddKey(duration, startValue, trinity.Tr2CurveInterpolation.LINEAR) 196 return uicore.animations.Play(curve, sprite, 'opacity', loops, None, False) 197 198 def GetRatio(self, timeLeft): 199 ratio = timeLeft / float(self.timerData.maxTimeout) 200 ratio = min(1.0, max(0.0, ratio)) 201 return ratio 202 203 def Animate_Thread(self): 204 self.StopActiveAnimation() 205 while not self.destroyed and self.expiryTime is not None: 206 if not self.rewind: 207 if self.ratio <= 0.0: 208 break 209 timeLeft = self.expiryTime - self.GetTime() 210 ratio = self.GetRatio(timeLeft) 211 self.SetRatio(ratio) 212 if timeLeft < BLINK_BEFORE_DONE_TIME: 213 self.PlayIconBlink() 214 else: 215 self.StopIconBlink() 216 uthread2.sleep(0.05) 217 218 if self.callback: 219 self.callback(self) 220 221 def PlayIconBlink(self): 222 if self.iconBlink is None: 223 self.iconBlink = self.FlipFlop(self.icon, startValue=1.0, endValue=0.0) 224 if self.timerData.endingAudioEvent: 225 sm.GetService('audio').SendUIEvent(self.timerData.endingAudioEvent) 226 227 def StopIconBlink(self): 228 if self.iconBlink is not None: 229 self.iconBlink.Stop() 230 self.iconBlink = None 231 self.icon.opacity = 1.0 232 233 def EndAnimation(self): 234 self.SetRatio(0.0) 235 uicore.animations.MoveOutBottom(self.pointerSprite, amount=9, duration=0.3, sleep=False) 236 self.content.scalingCenter = (0.5, 0.5) 237 uicore.animations.Tr2DScaleTo(self.content, startScale=(1.0, 1.0), endScale=(0.8, 0.8), duration=0.4, sleep=True) 238 239 def OnMouseEnter(self, *args): 240 uthread.new(self.ShowHide) 241 242 def ShowHide(self): 243 uthread2.sleep(0.25) 244 if uicore.uilib.mouseOver is self.content: 245 self.showHint = True 246 if self.timerHint is None: 247 left, top, width, height = self.content.GetAbsolute() 248 self.timerHint = self.hintClass(parent=uicore.layer.abovemain, left=left + 16, top=top + 16, timerData=self.timerData, parentTimer=self) 249 250 def ShiftLeft(self): 251 uicore.animations.MoveInFromRight(self, self.width, duration=0.5) 252 253 def SetCounter(self, count): 254 if count is None or count <= 1: 255 if self.counterText is not None: 256 self.counterText.Close() 257 self.counterText = None 258 else: 259 if self.counterText is None: 260 self.counterText = eveLabel.EveHeaderLarge(parent=self.content, name='counter', left=34, top=-2, bold=True, color=self.timerData.color) 261 text = str(count) if count < 10 else '9+' 262 self.counterText.text = text 263 264 def PlayActiveAnimation(self): 265 self.activeAnimationCurves = ((self.pointerSprite, self.FlipFlop(self.pointerSprite, startValue=1.0, endValue=0.75, duration=1.0, loops=uiconst.ANIM_REPEAT)), (self.gaugeCircular, self.FlipFlop(self.gaugeCircular, startValue=1.0, endValue=0.75, duration=1.0, loops=uiconst.ANIM_REPEAT))) 266 267 def StopActiveAnimation(self): 268 if self.activeAnimationCurves is not None: 269 for sprite, animCurve in self.activeAnimationCurves: 270 animCurve.Stop() 271 sprite.opacity = 1.0 272 273 self.activeAnimationCurves = None 274 275 276 class TimerContainer(UiHiderMixin, Container): 277 __notifyevents__ = ['OnWeaponsTimerUpdate', 278 'OnPvpTimerUpdate', 279 'OnCriminalTimerUpdate', 280 'OnNpcTimerUpdate', 281 'OnCombatTimersUpdated', 282 'OnCrimewatchEngagementUpdated', 283 'OnBoosterUpdated', 284 'OnDisapprovalTimerUpdate', 285 'OnJumpTimersUpdated', 286 'OnJumpCloakUpdated', 287 'OnJumpCloakCancelled', 288 'OnRestoringInvulnUpdated', 289 'OnInvulunOnUndockingUpdated', 290 'OnInvulnCancelled', 291 'OnAbyssalContentFinished', 292 'OnVoidSpaceContentFinished', 293 'OnWarStatusUpdated', 294 'OnEmanationLockUpdated'] 295 default_name = 'unique_UI_crimewatchTimers' 296 uniqueUiName = uniqueNameConst.UNIQUE_NAME_CRIMEWATCH_TIMERS 297 default_height = 32 298 default_width = 96 + 16 299 default_padBottom = 6 300 default_align = uiconst.TOTOP 301 302 def ApplyAttributes(self, attributes): 303 super(TimerContainer, self).ApplyAttributes(attributes) 304 self.warCont = AtWarCont(parent=self, align=uiconst.TOLEFT) 305 sm.RegisterNotify(self) 306 self.uiCriticalSectionsByTimerType = {} 307 for timerType, timerData in CRIMEWATCH_TIMER_DATA.iteritems(): 308 setattr(self, timerData.timerAttributeName, None) 309 if timerType not in self.uiCriticalSectionsByTimerType: 310 criticalSection = uthread.CriticalSection('uiTimerCriticalSection:%s' % timerData.timerAttributeName) 311 self.uiCriticalSectionsByTimerType[timerType] = criticalSection 312 313 self.crimewatchSvc = sm.GetService('crimewatchSvc') 314 self.warSvc = sm.GetService('war') 315 uthread.new(self.OnCombatTimersUpdated) 316 317 def Release(self): 318 sm.UnregisterNotify(self) 319 for timerData in CRIMEWATCH_TIMER_DATA.itervalues(): 320 timer = getattr(self, timerData.timerAttributeName, None) 321 if timer is not None and timer.animationThread is not None: 322 timer.animationThread.kill() 323 324 def OnCombatTimersUpdated(self): 325 self.OnWeaponsTimerUpdate(doAlert=False, *self.crimewatchSvc.GetWeaponsTimer()) 326 self.OnNpcTimerUpdate(doAlert=False, *self.crimewatchSvc.GetNpcTimer()) 327 self.OnPvpTimerUpdate(doAlert=False, *self.crimewatchSvc.GetPvpTimer()) 328 self.OnCriminalTimerUpdate(doAlert=False, *self.crimewatchSvc.GetCriminalTimer()) 329 self.OnDisapprovalTimerUpdate(doAlert=False, *self.crimewatchSvc.GetDisapprovalTimer()) 330 self.OnCrimewatchEngagementUpdated(None, None, doAlert=False) 331 self.OnBoosterUpdated() 332 self.OnJumpTimersUpdated(doAlert=False, *self.crimewatchSvc.GetJumpTimers()) 333 self.OnWarStatusUpdated(self.warSvc.IsPlayerCurrentlyAtWarOrInFW(), doAlert=False) 334 uthread2.start_tasklet(self._UpdateEmanationLock) 335 336 def OnWeaponsTimerUpdate(self, state, expiryTime, doAlert = True): 337 with self.uiCriticalSectionsByTimerType[TimerType.Weapons]: 338 if state in (const.weaponsTimerStateActive, const.weaponsTimerStateInherited): 339 timer = self.GetTimer(TimerType.Weapons) 340 timer.SetExpiryTime(None, doAlert) 341 elif expiryTime is not None: 342 timer = self.GetTimer(TimerType.Weapons) 343 timer.SetExpiryTime(expiryTime, doAlert) 344 else: 345 self.DeleteTimer(TimerType.Weapons) 346 347 def OnNpcTimerUpdate(self, state, expiryTime, doAlert = True): 348 with self.uiCriticalSectionsByTimerType[TimerType.Npc]: 349 if state in (const.npcTimerStateActive, const.npcTimerStateInherited): 350 timer = self.GetTimer(TimerType.Npc) 351 timer.SetExpiryTime(None, doAlert) 352 elif expiryTime is not None: 353 timer = self.GetTimer(TimerType.Npc) 354 timer.SetExpiryTime(expiryTime, doAlert) 355 else: 356 self.DeleteTimer(TimerType.Npc) 357 358 def OnPvpTimerUpdate(self, state, expiryTime, doAlert = True): 359 with self.uiCriticalSectionsByTimerType[TimerType.Pvp]: 360 if state in (const.pvpTimerStateActive, const.pvpTimerStateInherited): 361 timer = self.GetTimer(TimerType.Pvp) 362 timer.SetExpiryTime(None, doAlert) 363 elif expiryTime is not None: 364 timer = self.GetTimer(TimerType.Pvp) 365 timer.SetExpiryTime(expiryTime, doAlert) 366 else: 367 self.DeleteTimer(TimerType.Pvp) 368 369 def OnDisapprovalTimerUpdate(self, state, expiryTime, doAlert = True): 370 with self.uiCriticalSectionsByTimerType[TimerType.Disapproval]: 371 if state in (const.disapprovalTimerStateActive, const.disapprovalTimerStateInherited): 372 timer = self.GetTimer(TimerType.Disapproval) 373 timer.SetExpiryTime(None, doAlert) 374 elif state == const.disapprovalTimerStateTimer and expiryTime is not None: 375 timer = self.GetTimer(TimerType.Disapproval) 376 timer.SetExpiryTime(expiryTime, doAlert) 377 else: 378 self.DeleteTimer(TimerType.Disapproval) 379 380 def OnCriminalTimerUpdate(self, state, expiryTime, doAlert = True): 381 with self.uiCriticalSectionsByTimerType[TimerType.Suspect]: 382 if state in (const.criminalTimerStateActiveSuspect, const.criminalTimerStateInheritedSuspect): 383 timer = self.GetTimer(TimerType.Suspect) 384 timer.SetExpiryTime(None, doAlert) 385 elif state == const.criminalTimerStateTimerSuspect and expiryTime is not None: 386 timer = self.GetTimer(TimerType.Suspect) 387 timer.SetExpiryTime(expiryTime, doAlert) 388 elif state in (const.criminalTimerStateActiveCriminal, const.criminalTimerStateInheritedCriminal): 389 timer = self.GetTimer(TimerType.Criminal) 390 timer.SetExpiryTime(None, doAlert) 391 elif state == const.criminalTimerStateTimerCriminal and expiryTime is not None: 392 timer = self.GetTimer(TimerType.Criminal) 393 timer.SetExpiryTime(expiryTime, doAlert) 394 else: 395 self.DeleteTimer(TimerType.Suspect) 396 397 def OnCrimewatchEngagementUpdated(self, otherCharId, timeout, doAlert = True): 398 engagements = self.crimewatchSvc.GetMyEngagements() 399 if len(engagements) == 0: 400 self.DeleteTimer(TimerType.Engagement) 401 else: 402 timer = self.GetTimer(TimerType.Engagement) 403 onGoingEngagement = any((_timeout == const.crimewatchEngagementTimeoutOngoing for _timeout in engagements.itervalues())) 404 if onGoingEngagement: 405 timeout = None 406 else: 407 timeout = max((_timeout for _timeout in engagements.itervalues())) 408 timer.SetExpiryTime(timeout, doAlert) 409 timer.SetCounter(len(engagements)) 410 411 def OnBoosterUpdated(self, doAlert = True): 412 boosters = self.crimewatchSvc.GetMyBoosters() 413 boosterList = [ b for b in boosters if b.boosterDuration ] 414 if len(boosterList) == 0: 415 self.DeleteTimer(TimerType.Booster) 416 else: 417 timer = self.GetTimer(TimerType.Booster) 418 boosterList.sort(key=lambda x: x.expiryTime, reverse=True) 419 longestLastingBooster = boosterList[0] 420 timeout = longestLastingBooster.expiryTime 421 maxDuration = longestLastingBooster.boosterDuration 422 timer.SetExpiryTime(timeout, doAlert, maxDuration * 10000) 423 timer.SetCounter(len(boosterList)) 424 425 def OnJumpTimersUpdated(self, jumpActivation, jumpFatigue, lastUpdated, doAlert = False): 426 if jumpFatigue and jumpFatigue > gametime.GetWallclockTime(): 427 timer = self.GetTimer(TimerType.JumpFatigue) 428 timer.SetExpiryTime(jumpFatigue, doAlert, jumpFatigue - lastUpdated) 429 else: 430 self.DeleteTimer(TimerType.JumpFatigue) 431 if jumpActivation and jumpActivation > gametime.GetWallclockTime(): 432 self.GetTimer(TimerType.JumpActivation).SetExpiryTime(jumpActivation, doAlert, jumpActivation - lastUpdated) 433 else: 434 self.DeleteTimer(TimerType.JumpActivation) 435 436 def OnWarStatusUpdated(self, atWar, doAlert = True): 437 self.warCont.ShowIcon(animate=doAlert) if atWar else self.warCont.HideIcon(animate=doAlert) 438 439 def OnJumpCloakUpdated(self, shipID, endTime, duration): 440 self.GetTimer(TimerType.JumpCloak).SetExpiryTime(endTime, maxDuration=duration, doAlert=True) 441 442 def OnJumpCloakCancelled(self, shipID): 443 self.DeleteTimer(TimerType.JumpCloak) 444 445 def OnRestoringInvulnUpdated(self, shipID, endTime, duration): 446 self._SetInvulnTimerExpiryTime(endTime, duration) 447 448 def OnInvulunOnUndockingUpdated(self, shipID, endTime, duration): 449 self._SetInvulnTimerExpiryTime(endTime, duration) 450 451 def _SetInvulnTimerExpiryTime(self, endTime, duration): 452 with self.uiCriticalSectionsByTimerType[TimerType.Invulnerable]: 453 timer = self.GetTimer(TimerType.Invulnerable) 454 timer.SetExpiryTime(endTime, maxDuration=duration, doAlert=True) 455 456 def OnInvulnCancelled(self, shipID): 457 with self.uiCriticalSectionsByTimerType[TimerType.Invulnerable]: 458 self.DeleteTimer(TimerType.Invulnerable) 459 460 def SetAbyssalTimer(self, endTime): 461 self.SetTimerContentExpiry(TimerType.AbyssalContentExpiration, endTime) 462 463 def SetAbyssalPvpTimer(self, endTime): 464 self.SetTimerContentExpiry(TimerType.AbyssalPvpExpiration, endTime) 465 466 def SetVoidSpaceTimer(self, endTime): 467 self.SetTimerContentExpiry(TimerType.VoidSpaceContentExpiration, endTime) 468 469 def SetTimerContentExpiry(self, timerType, endTime): 470 with self.uiCriticalSectionsByTimerType[timerType]: 471 timer = self.GetTimer(timerType) 472 timer.SetExpiryTime(endTime, False) 473 474 def OnAbyssalContentFinished(self, content_id, timer_type): 475 if not sm.GetService('abyss').is_active_content(content_id): 476 return 477 with self.uiCriticalSectionsByTimerType[timer_type]: 478 self.DeleteTimer(timer_type) 479 480 def OnVoidSpaceContentFinished(self, content_id, timer_type): 481 if not sm.GetService('voidSpaceSvc').is_content_active(content_id): 482 return 483 with self.uiCriticalSectionsByTimerType[timer_type]: 484 self.DeleteTimer(timer_type) 485 486 def OnEmanationLockUpdated(self, lock_details): 487 if lock_details is None or lock_details.expiry_time < gametime.now(): 488 with self.uiCriticalSectionsByTimerType[TimerType.EmanationLock]: 489 self.DeleteTimer(TimerType.EmanationLock) 490 return 491 with self.uiCriticalSectionsByTimerType[TimerType.EmanationLock]: 492 timer = self.GetTimer(TimerType.EmanationLock) 493 timer.SetExpiryTime(datetime_to_filetime(lock_details.expiry_time), doAlert=True) 494 hasShownHighlight = settings.char.ui.Get(SETTINGS_FIRST_HIGHLIGHT_SHOWN, False) 495 if hasShownHighlight: 496 return 497 settings.char.ui.Set(SETTINGS_FIRST_HIGHLIGHT_SHOWN, True) 498 sm.GetService('uiHighlightingService').highlight_ui_element_by_name(ui_element_name=timer.name, message=GetByLabel('UI/Crimewatch/Timers/EmanationLockHighlight'), default_direction=UiHighlightDirections.RIGHT, offset=-10, fadeout_seconds=10) 499 500 def _UpdateEmanationLock(self): 501 messenger = get_gate_lock_messenger(sm.GetService('publicGatewaySvc')) 502 lock_details = GateLockController.get_instance(messenger).get_current_system_lock() 503 self.OnEmanationLockUpdated(lock_details) 504 505 def DeleteTimer(self, timerType): 506 idx = None 507 timerName = CRIMEWATCH_TIMER_DATA[timerType].timerAttributeName 508 timer = getattr(self, timerName, None) 509 if timer is not None: 510 if timer in self.children: 511 idx = self.children.index(timer) 512 timer.EndAnimation() 513 timer.Close() 514 setattr(self, timerName, None) 515 logger.debug('Closed Timer %s', timerName) 516 if idx is not None: 517 for timer in self.children[idx:idx + 1]: 518 timer.ShiftLeft() 519 520 def DeleteWhenFinished(self, timer): 521 with self.uiCriticalSectionsByTimerType[timer.timerType]: 522 self.DeleteTimer(timer.timerType) 523 524 def GetTimer(self, timerType): 525 timerData = CRIMEWATCH_TIMER_DATA[timerType] 526 timerAttributeName = timerData.timerAttributeName 527 timer = getattr(self, timerAttributeName) 528 if timer is None: 529 timer = Timer(parent=self, name=timerAttributeName, timerType=timerType, callback=getattr(self, timerData.callbackName) if timerData.callbackName else None) 530 setattr(self, timerAttributeName, timer) 531 logger.debug('Created Timer %s', timerAttributeName) 532 if timer.timerType != timerType: 533 timer.SetTimerType(timerType) 534 return timer 535 536 def GetExistingTimer(self, timerType): 537 timerName = CRIMEWATCH_TIMER_DATA[timerType].timerAttributeName 538 return getattr(self, timerName, None)