infoPanelFactionalWarfare.py (21701B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\infoPanels\infoPanelFactionalWarfare.py 2 import carbonui.const as uiconst 3 import evelink 4 import localization 5 import uthread 6 from carbon.common.script.util import timerstuff 7 from carbonui import TextColor 8 from carbonui.primitives.container import Container 9 from carbonui.primitives.containerAutoSize import ContainerAutoSize 10 from carbonui.primitives.sprite import Sprite 11 from carbonui.uicore import uicore 12 from characterdata.races import get_race_name 13 from eve.client.script.ui.control import eveLabel 14 from eve.client.script.ui.control.eveLabel import EveLabelMedium, EveLabelLarge, EveLabelSmall 15 from eve.client.script.ui.control.gauge import Gauge 16 from eve.client.script.ui.shared.factionalWarfare.fwSystemBenefitIcon import FWSystemBenefitIcon 17 from eve.client.script.ui.shared.infoPanels.InfoPanelBase import InfoPanelBase 18 from eve.client.script.ui.shared.infoPanels.const import infoPanelConst 19 from evelink.client import owner_link 20 from factionwarfare.client.text import GetSystemCaptureStatusText 21 from factionwarfare.maptags.client.mapTagDataProvider import NoMapTagDataAvailableError 22 from fwwarzone.client.dashboard.const import FACTION_ID_TO_COLOR, ADJACENCY_TO_LABEL_SYSTEM_TEXT 23 from fwwarzone.client.dashboard.gauges.contestedGauge import ContestedFWSystemGauge 24 from fwwarzone.client.util import GetAttackerDefenderColors 25 from spacecomponents.common.componentConst import FW_SCOREBOARD 26 from spacecomponents.common.data import get_space_component_for_type 27 from eve.common.lib import appConst 28 29 class InfoPanelFactionalWarfare(InfoPanelBase): 30 default_name = 'InfoPanelFactionalWarfare' 31 default_iconTexturePath = 'res:/UI/Texture/Classes/InfoPanels/FactionalWarfare.png' 32 default_state = uiconst.UI_PICKCHILDREN 33 default_height = 120 34 label = 'UI/Map/StarMap/FactionalWarfare' 35 hasSettings = False 36 panelTypeID = infoPanelConst.PANEL_FACTIONAL_WARFARE 37 COLOR_RED = (0.5, 0.0, 0.0, 1.0) 38 COLOR_WHITE = (0.5, 0.5, 0.5, 1.0) 39 ICONSIZE = 20 40 __notifyevents__ = InfoPanelBase.__notifyevents__ + ['OnWarzoneOccupationStateUpdated_Local', 41 'OnSolarsystemAdvantageStateUpdated_Local', 42 'OnFwBattlefieldUpdated', 43 'OnFwBattlefieldAdded'] 44 45 def ApplyAttributes(self, attributes): 46 self.fwWarzoneSvc = sm.GetService('fwWarzoneSvc') 47 self.fwVictoryPointSvc = sm.GetService('fwVictoryPointSvc') 48 self.statusLabel = None 49 self.compactTitle = None 50 self.adjacencyLabel = None 51 self.netAdvantageLabel = None 52 InfoPanelBase.ApplyAttributes(self, attributes) 53 self.controlGauge = None 54 self.headerControlGauge = None 55 self.isGaugeInitialized = False 56 self.benefitIcons = [] 57 self.headerTextCont = Container(name='headerTextCont', parent=self.headerCont, align=uiconst.TOALL) 58 link = evelink.local_service_link(method='OpenMilitia', text=localization.GetByLabel('UI/FactionWarfare/FactionalWarfare')) 59 self.title = self.headerCls(name='title', text=link, parent=self.headerTextCont, align=uiconst.CENTERLEFT, state=uiconst.UI_NORMAL) 60 self.compactTitle = eveLabel.EveLabelMedium(name='compactTitle', text=link, parent=self.headerTextCont, align=uiconst.CENTERLEFT, state=uiconst.UI_NORMAL) 61 self.compactTitle.Hide() 62 topCont = ContainerAutoSize(name='topCont', parent=self.mainCont, align=uiconst.TOTOP, alignMode=uiconst.TOTOP) 63 self.bottomContainer = ContainerAutoSize(parent=self.mainCont, name='bottomContainer', align=uiconst.TOTOP) 64 self.scoreboardCont = ContainerAutoSize(parent=self.mainCont, name='scoreboardCont', align=uiconst.TOTOP) 65 fwOccupationState = self.fwWarzoneSvc.GetLocalOccupationState() 66 textCont = VerticalCenteredContainer(parent=topCont, name='textCont', align=uiconst.TOTOP) 67 if fwOccupationState: 68 gaugeRadius = 25 69 gaugeSizeCont = gaugeRadius * 2 70 textCont.padLeft = self.bottomContainer.padLeft = gaugeSizeCont + 10 71 gaugeCont = Container(name='gaugeCont', parent=topCont, align=uiconst.CENTERLEFT, pos=(0, 72 0, 73 gaugeSizeCont, 74 gaugeSizeCont)) 75 topCont.minHeight = gaugeSizeCont 76 self.controlGauge = self.AddGauge(fwOccupationState, gaugeCont, uiconst.CENTER, gaugeRadius) 77 self.headerControlGauge = self.AddGauge(fwOccupationState, self.headerCont, uiconst.CENTERLEFT, 10, False) 78 self.headerControlGauge.chart.state = uiconst.UI_DISABLED 79 self.compactTitle.padLeft = self.headerControlGauge.width + 10 80 self.headerControlGauge.OnClick = lambda *args: sm.GetService('cmd').OpenMilitia() 81 self.headerControlGauge.Hide() 82 self.statusLabel = eveLabel.EveLabelMedium(name='statusLabel', parent=textCont, align=uiconst.TOTOP, state=uiconst.UI_NORMAL) 83 if not _IsBulwarkSolarsystem(): 84 adjacencyText = self.GetAdjacencyText() 85 self.adjacencyLabel = eveLabel.EveLabelMedium(name='adjacencyLabel', parent=textCont, align=uiconst.TOTOP, state=uiconst.UI_NORMAL, top=2, text=adjacencyText) 86 self.netAdvantageLabel = EveLabelSmall(parent=textCont, align=uiconst.TOTOP, text='', state=uiconst.UI_NORMAL, top=10) 87 self.ConstructScoreboards() 88 self.bottomContainer.EnableAutoSize() 89 self.mainCont.EnableAutoSize() 90 self.UpdateLabels() 91 uthread.new(self.UpdateAdvantageSection_thread) 92 93 def _GetAdvantageTextAndHint(self): 94 occupationState = self.fwWarzoneSvc.GetOccupationState(session.solarsystemid2) 95 if occupationState is None: 96 return (None, None) 97 defenderId = occupationState.occupierID 98 attackerId = occupationState.attackerID 99 advantageState = sm.GetService('fwAdvantageSvc').GetAdvantageState(session.solarsystemid2) 100 netScore = advantageState.GetNetAdvantageScore(defenderId, attackerId) 101 winner = None 102 if netScore > 0: 103 winner = defenderId 104 elif netScore < 0: 105 winner = attackerId 106 displayScore = netScore 107 if netScore < 0: 108 displayScore = netScore * -1 109 if winner is not None: 110 percentageBonusText = u'{0:.0%}'.format(displayScore) 111 winnerName = _GetRaceName(winner) 112 winnerNameLink = owner_link(winner, winnerName) 113 text = localization.GetByLabel('UI/FactionWarfare/shortAdvantageLine', factionName=winnerNameLink, netAdvantagePercent=percentageBonusText) 114 contributionText = u'{0:.0%}'.format(advantageState.GetContributionScore(winner)) 115 floorText = u'{0:.0%}'.format(advantageState.GetTerrainScore(winner)) 116 hint = localization.GetByLabel('UI/FactionWarfare/advantagebreakdownTooltip', objectives=contributionText, floor=floorText) 117 return (text, hint) 118 else: 119 return (localization.GetByLabel('UI/FactionWarfare/noFactionHasAdvantageShortLine'), None) 120 121 def UpdateAdvantageSection_thread(self): 122 if self.netAdvantageLabel is None: 123 return 124 text, hint = self._GetAdvantageTextAndHint() 125 if text is not None: 126 self.netAdvantageLabel.SetText(text) 127 self.netAdvantageLabel.hint = hint 128 129 def AddGauge(self, fwOccupationState, parent, align, gaugeRadius, showAdjacency = True): 130 occupierID = fwOccupationState.occupierID 131 attackerID = fwOccupationState.attackerID 132 gauge = ContestedFWSystemGauge(parent=parent, align=align, systemId=session.solarsystemid2, radius=gaugeRadius, attackerColor=FACTION_ID_TO_COLOR[attackerID], defenderColor=FACTION_ID_TO_COLOR[occupierID], adjacencyState=fwOccupationState.adjacencyState, displayAdjacencyIcon=showAdjacency) 133 return gauge 134 135 @staticmethod 136 def IsAvailable(): 137 if sm.GetService('fwWarzoneSvc').IsWarzoneSolarSystem(session.solarsystemid2): 138 return True 139 if _IsBulwarkSolarsystem(): 140 return True 141 return False 142 143 def ConstructNormal(self): 144 if not self.IsAvailable(): 145 return 146 self.UpdateLabels() 147 upgradeLevel = sm.GetService('facwar').GetSolarSystemUpgradeLevel(session.solarsystemid2) 148 self.bottomContainer.Flush() 149 self.benefitIcons = [] 150 if upgradeLevel: 151 self.ConstructBenefitIcons(upgradeLevel) 152 self.UpdateGauges() 153 154 def ConstructBenefitIcons(self, upgradeLevel): 155 iconCont = Container(name='iconCont', align=uiconst.TOTOP, parent=self.bottomContainer, padTop=6, height=36) 156 benefits = sm.GetService('facwar').GetSystemUpgradeLevelBenefits(upgradeLevel) 157 benefits = list(benefits) 158 benefits.reverse() 159 for benefitType, benefitValue in benefits: 160 benefitIcon = FWSystemBenefitIcon(parent=iconCont, align=uiconst.TOLEFT, padRight=12, benefitType=benefitType, benefitValue=benefitValue, opacity=0.0) 161 self.benefitIcons.append(benefitIcon) 162 163 def UpdateLabels(self): 164 text = self.GetStatusText() 165 if self.statusLabel: 166 self.statusLabel.text = text 167 if self.compactTitle: 168 self.compactTitle.text = text 169 if self.adjacencyLabel: 170 self.adjacencyLabel.text = self.GetAdjacencyText() 171 172 def GetStatusText(self): 173 if _IsBulwarkSolarsystem(): 174 solarsystemData = cfg.mapSystemCache.Get(session.solarsystemid2) 175 try: 176 factionID = solarsystemData.factionID 177 except AttributeError: 178 factionID = None 179 180 statusText = localization.GetByLabel('UI/FactionWarfare/frontlinesDashboard/systemBulwark') 181 else: 182 factionID = self.fwWarzoneSvc.GetSystemOccupier(session.solarsystemid2) 183 victoryPointState = self.fwVictoryPointSvc.GetVictoryPointState(session.solarsystemid2) 184 statusText = GetSystemCaptureStatusText(victoryPointState) 185 if factionID is None: 186 return '' 187 factionOwnerLink = owner_link(factionID) 188 if statusText: 189 text = '%s: %s' % (factionOwnerLink, statusText) 190 else: 191 text = factionOwnerLink 192 return text 193 194 def GetAdjacencyText(self): 195 fwOccupationState = self.fwWarzoneSvc.GetLocalOccupationState() 196 if fwOccupationState: 197 adjacencyText = ADJACENCY_TO_LABEL_SYSTEM_TEXT[fwOccupationState.adjacencyState] 198 else: 199 adjacencyText = '' 200 return adjacencyText 201 202 def ConstructCompact(self): 203 self.UpdateLabels() 204 self.UpdateGauges() 205 206 def OnStartModeChanged(self, oldMode): 207 uthread.new(self._OnStartModeChanged, oldMode) 208 209 def OnEndModeChanged(self, oldMode): 210 if self.mode == infoPanelConst.MODE_NORMAL and oldMode: 211 for i, icon in enumerate(self.benefitIcons): 212 uicore.animations.BlinkIn(icon, endVal=0.75, timeOffset=0.2 + i * 0.05) 213 214 else: 215 for icon in self.benefitIcons: 216 icon.opacity = 0.75 217 218 def _OnStartModeChanged(self, oldMode): 219 if self.mode == infoPanelConst.MODE_COMPACT: 220 if oldMode: 221 uicore.animations.FadeOut(self.title, duration=0.3, sleep=True, callback=self.title.Hide) 222 if self.headerControlGauge is not None: 223 self.headerControlGauge.Show() 224 uicore.animations.FadeTo(self.headerControlGauge, 0.0, 1.0, duration=0.3) 225 self.compactTitle.Show() 226 uicore.animations.FadeTo(self.compactTitle, 0.0, TextColor.NORMAL.opacity, duration=0.3) 227 else: 228 self.title.Hide() 229 if self.headerControlGauge is not None: 230 self.headerControlGauge.Show() 231 self.compactTitle.Show() 232 else: 233 if self.headerControlGauge is not None and self.headerControlGauge.display: 234 uicore.animations.FadeOut(self.headerControlGauge, duration=0.3, sleep=True, callback=self.headerControlGauge.Hide) 235 self.compactTitle.Hide() 236 self.title.Show() 237 uicore.animations.FadeTo(self.title, 0.0, TextColor.NORMAL.opacity, duration=0.3) 238 239 def UpdateGauges(self): 240 solarSystemID = session.solarsystemid2 241 victoryPointState = self.fwVictoryPointSvc.GetVictoryPointState(solarSystemID) 242 if victoryPointState is None: 243 return 244 occupationState = self.fwWarzoneSvc.GetLocalOccupationState() 245 if occupationState is None: 246 return 247 attackerColor, defenderColor = GetAttackerDefenderColors(solarSystemID) 248 if self.controlGauge is not None: 249 self.controlGauge.SetGaugeColors(attackerColor, defenderColor) 250 self.controlGauge.UpdateVictoryPointsState(victoryPointState) 251 self.controlGauge.UpdateAdjacencyState(occupationState.adjacencyState) 252 if self.headerControlGauge is not None: 253 self.headerControlGauge.SetGaugeColors(attackerColor, defenderColor) 254 self.headerControlGauge.UpdateVictoryPointsState(victoryPointState) 255 self.headerControlGauge.UpdateAdjacencyState(occupationState.adjacencyState) 256 257 def OnWarzoneOccupationStateUpdated_Local(self): 258 self.UpdateLabels() 259 self.UpdateGauges() 260 261 def OnSolarsystemAdvantageStateUpdated_Local(self): 262 uthread.new(self.UpdateAdvantageSection_thread) 263 264 def OnFwBattlefieldUpdated(self): 265 self.ConstructScoreboards() 266 267 def ConstructScoreboards(self): 268 self.scoreboardCont.Flush() 269 scoreboards = sm.GetService('fwWarzoneSvc').GetBattleFieldScoreboards() 270 ballpark = sm.GetService('michelle').GetBallpark() 271 if not ballpark: 272 return 273 for eachScoreboardID in scoreboards: 274 slimItem = ballpark.GetInvItem(eachScoreboardID) 275 if slimItem: 276 BattlefieldSection(name='BattlefieldSection_%s' % eachScoreboardID, parent=self.scoreboardCont, itemID=eachScoreboardID, typeID=slimItem.typeID) 277 278 def OnFwBattlefieldAdded(self, itemID, typeID, score): 279 for eachScoreboard in self.scoreboardCont.children: 280 if eachScoreboard.itemID == itemID: 281 eachScoreboard.SetValue(score) 282 return 283 284 b = BattlefieldSection(name='BattlefieldSection_%s' % itemID, parent=self.scoreboardCont, itemID=itemID, typeID=typeID) 285 b.SetValue(score) 286 287 288 class VerticalCenteredContainer(ContainerAutoSize): 289 290 def __init__(self, **kwargs): 291 kwargs['callback'] = self.on_size_change 292 super(VerticalCenteredContainer, self).__init__(**kwargs) 293 294 def on_size_change(self): 295 if self.children: 296 content_height = 0 297 for i, child in enumerate(self.children): 298 content_height += child.height + child.padTop + child.padBottom 299 if i > 0: 300 content_height += child.top 301 302 minHeight = getattr(self.parent, 'minHeight', 0) 303 height = max(self.height, minHeight) 304 adjusted_top = int(round((height - content_height) / 2.0)) 305 self.padTop = adjusted_top 306 307 308 FULL_GAUGE_HEIGHT = 6 309 SMALL_GAUGE_HEIGHT = 4 310 311 class BattlefieldSection(ContainerAutoSize): 312 default_padTop = 10 313 default_minHeight = 35 314 default_align = uiconst.TOTOP 315 default_alignMode = uiconst.TOBOTTOM 316 __notifyevents__ = ['OnFwScoreboardUpdated'] 317 318 def ApplyAttributes(self, attributes): 319 super(BattlefieldSection, self).ApplyAttributes(attributes) 320 self.itemID = attributes.itemID 321 self.typeID = attributes.typeID 322 fwObjectiveAttributes = get_space_component_for_type(self.typeID, FW_SCOREBOARD) 323 self.defenderThreshold = fwObjectiveAttributes.occupierWinsThreshold 324 self.attackerThreshold = fwObjectiveAttributes.attackerWinsThreshold 325 fwOccupationState = sm.GetService('fwWarzoneSvc').GetOccupationState(session.solarsystemid2) 326 if fwOccupationState: 327 self.defenderID = fwOccupationState.occupierID 328 self.attackerID = fwOccupationState.attackerID 329 else: 330 self.defenderID = None 331 self.attackerID = None 332 battleFieldSpriteCont = Container(parent=self, align=uiconst.BOTTOMLEFT, pos=(0, 0, 60, 35)) 333 battlefieldSprite = Sprite(name='battlefieldSprite', align=uiconst.CENTER, parent=battleFieldSpriteCont, texturePath='res:/UI/Texture/classes/frontlines/battlefield.png', state=uiconst.UI_DISABLED, pos=(-5, 0, 32, 32)) 334 rightCont = ContainerAutoSize(name='rightCont', parent=self, align=uiconst.TOBOTTOM, alignMode=uiconst.TOTOP, padLeft=battleFieldSpriteCont.left + battleFieldSpriteCont.width) 335 EveLabelMedium(name='label', parent=rightCont, align=uiconst.TOTOP, state=uiconst.UI_DISABLED, text=localization.GetByLabel('UI/FactionWarfare/frontlines/BattlefieldScoreboard')) 336 attackerColor, defenderColor = GetAttackerDefenderColors(session.solarsystemid2) 337 gaugeCont = Container(name='gaugeCont', parent=rightCont, align=uiconst.TOTOP, height=FULL_GAUGE_HEIGHT, padTop=8, padBottom=2) 338 self.leftGauge = Gauge(parent=gaugeCont, align=uiconst.TOTOP_NOPUSH, gaugeHeight=FULL_GAUGE_HEIGHT, state=uiconst.UI_PICKCHILDREN, color=defenderColor) 339 self.leftGauge.gauge.LoadTooltipPanel = self.LoadLeftGaugeTooltip 340 self.leftGauge.gauge.state = uiconst.UI_NORMAL 341 self.leftGauge.gaugeGradient.state = uiconst.UI_DISABLED 342 self.leftGauge.gaugeCont.state = uiconst.UI_PICKCHILDREN 343 self.leftGauge.HideBackground() 344 self.rightGauge = Gauge(parent=gaugeCont, align=uiconst.TOTOP_NOPUSH, height=FULL_GAUGE_HEIGHT, color=attackerColor, gaugeAlign=uiconst.TORIGHT_PROP, state=uiconst.UI_PICKCHILDREN) 345 self.rightGauge.gauge.LoadTooltipPanel = self.LoadRightGaugeTooltip 346 self.rightGauge.gauge.state = uiconst.UI_NORMAL 347 self.rightGauge.gaugeGradient.state = uiconst.UI_DISABLED 348 self.rightGauge.gaugeCont.state = uiconst.UI_PICKCHILDREN 349 self.rightGauge.HideBackground() 350 self.UpdateValueFromSlimItem() 351 sm.RegisterNotify(self) 352 353 def UpdateValueFromSlimItem(self): 354 slimItem = GetSlimItemForItemID(self.itemID) 355 if not slimItem: 356 return 357 value = slimItem.component_fwScoreboard_score or 0 358 self.SetValue(value) 359 360 def SetValue(self, newScore): 361 pointsInGauges = float(abs(self.defenderThreshold) + self.attackerThreshold) 362 progress = (abs(self.defenderThreshold) + newScore) / pointsInGauges 363 self.leftGauge.SetValue(1 - progress, animate=False) 364 self.rightGauge.SetValue(progress, animate=False) 365 if newScore == 0: 366 self.leftGauge.gaugeCont.height = FULL_GAUGE_HEIGHT 367 self.rightGauge.gaugeCont.height = FULL_GAUGE_HEIGHT 368 self.leftGauge.padTop = 0 369 self.rightGauge.padTop = 0 370 else: 371 self.leftGauge.gaugeCont.height = FULL_GAUGE_HEIGHT if newScore < 0 else SMALL_GAUGE_HEIGHT 372 self.rightGauge.gaugeCont.height = FULL_GAUGE_HEIGHT if newScore > 0 else SMALL_GAUGE_HEIGHT 373 self.leftGauge.padTop = 0 if newScore < 0 else 1 374 self.rightGauge.padTop = 0 if newScore > 0 else 1 375 376 def LoadLeftGaugeTooltip(self, tooltipPanel, *args): 377 tooltipPanel.LoadGeneric1ColumnTemplate() 378 label = tooltipPanel.AddLabelMedium() 379 updateArgs = (label, self.leftGauge, self.defenderID) 380 tooltipUpdated = self._UpdateTooltip(*updateArgs) 381 if tooltipUpdated: 382 self.leftGaugeTimer = timerstuff.AutoTimer(1000, self._UpdateTooltipLeftGauge_thread, *updateArgs) 383 384 def _UpdateTooltipLeftGauge_thread(self, label, gauge, ownerID): 385 if not self._UpdateTooltip(label, gauge, ownerID): 386 self.leftGaugeTimer = None 387 388 def LoadRightGaugeTooltip(self, tooltipPanel, *args): 389 tooltipPanel.LoadGeneric1ColumnTemplate() 390 label = tooltipPanel.AddLabelMedium() 391 updateArgs = (label, self.rightGauge, self.attackerID) 392 tooltipUpdated = self._UpdateTooltip(*updateArgs) 393 if tooltipUpdated: 394 self.rightGaugeTimer = timerstuff.AutoTimer(1000, self._UpdateTooltipRightGauge_thread, *updateArgs) 395 396 def _UpdateTooltipRightGauge_thread(self, label, gauge, ownerID): 397 if not self._UpdateTooltip(label, gauge, ownerID): 398 self.rightGaugeTimer = None 399 400 def _UpdateTooltip(self, label, gauge, ownerID): 401 if label.destroyed or gauge.destroyed: 402 return False 403 text = self._GetTooltipText(ownerID, gauge.value) 404 label.SetText(text) 405 return True 406 407 def _GetTooltipText(self, ownerID, value): 408 textList = [] 409 if ownerID: 410 textList.append(cfg.eveowners.Get(ownerID).name) 411 textList.append(localization.GetByLabel('UI/Common/Percentage', percentage=value * 100)) 412 return '<br>'.join(textList) 413 414 def OnFwScoreboardUpdated(self, itemID, score): 415 if itemID == self.itemID: 416 self.SetValue(score) 417 418 419 def GetSlimItemForItemID(itemID): 420 ballpark = sm.GetService('michelle').GetBallpark() 421 if not ballpark: 422 return 423 return ballpark.GetInvItem(itemID) 424 425 426 def _GetRaceName(factionID): 427 raceID = appConst.raceByFaction.get(factionID) 428 if not raceID: 429 return '' 430 occupierRaceName = get_race_name(raceID) 431 return occupierRaceName 432 433 434 def _IsBulwarkSolarsystem(): 435 try: 436 return sm.GetService('fwWarzoneSvc').GetMapTagProvider().is_bulwark_system(session.solarsystemid2) 437 except NoMapTagDataAvailableError: 438 return False