moduleButtonTooltip.py (58195B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\inflight\shipModuleButton\moduleButtonTooltip.py 2 import appConst 3 import carbonui.const as uiconst 4 import dogma.attributes.groups as dogma_attr_groups 5 import dogma.data as dogma_data 6 import gametime 7 from carbonui.text.styles import TextBody 8 from carbonui.primitives.container import Container 9 from carbon.common.script.util.timerstuff import AutoTimer 10 from dogma import units 11 from dogma.const import attributeSpeedBoostFactor, attributeMassAddition, attributeSpeedFactor, attributeMaxVelocity 12 from dogma.const import attributeMass 13 from eve.client.script.ui.control.gauge import Gauge 14 from eve.client.script.ui.control.tooltips import TooltipPanel, ShortcutHint 15 from eve.client.script.ui.crimewatch.crimewatchConst import Colors as CrimeWatchColors 16 import math 17 from carbon.common.script.util.format import FmtDist, FmtDate 18 from eve.client.script.ui.control.eveIcon import Icon 19 from eve.client.script.ui.eveThemeColor import THEME_ACCENT 20 from eve.client.script.ui.inflight import shipHud 21 from eve.client.script.ui.inflight.shipModuleButton.attributeValueRowContainer import AttributeValueRowContainer 22 from eve.client.script.ui.shared.fittingScreen import ACTIVE, OVERHEATED 23 from eve.client.script.ui.tooltips.tooltipsWrappers import TooltipBaseWrapper 24 from eve.client.script.ui.util.uix import GetTechLevelIcon 25 from eve.common.lib import appConst as const 26 from eve.common.script.sys.eveCfg import GetActiveShip 27 import evetypes 28 from inventorycommon.const import groupPropulsionModule 29 from localization.formatters import FormatTimeIntervalShort, FormatTimeIntervalShortWritten 30 from localization.formatters.timeIntervalFormatters import FormatSeconds 31 from shipfitting.fittingDogmaLocationUtil import GetTurretDps, GetLauncherDps, GetMissleDamageMultiplier, GetDotDps, GetTurretDpsWithMax 32 import localization 33 from carbonui.uicore import uicore 34 import blue 35 from utillib import KeyVal 36 RESISTANCE_BONUS_ATTRIBUTES = [const.attributeEmDamageResistanceBonus, 37 const.attributeExplosiveDamageResistanceBonus, 38 const.attributeKineticDamageResistanceBonus, 39 const.attributeThermalDamageResistanceBonus] 40 DL_NAME_FITTING = 'FittingDogmaLocation' 41 42 class TooltipModuleWrapper(TooltipBaseWrapper): 43 44 def CreateTooltip(self, parent, owner, idx): 45 self.tooltipPanel = ModuleButtonTooltip(parent=parent, owner=owner, idx=idx) 46 return self.tooltipPanel 47 48 49 class ModuleButtonTooltip(TooltipPanel): 50 infoFunctionNamesForCategories = {} 51 infoFunctionNames = {const.groupCompressors: 'AddCompressorInfo', 52 const.groupMiningLaser: 'AddMiningLaserInfo', 53 const.groupStripMiner: 'AddMiningLaserInfo', 54 const.groupFrequencyMiningLaser: 'AddMiningLaserInfo', 55 const.groupGasCloudHarvester: 'AddMiningLaserInfo', 56 const.groupGasCloudHoarder: 'AddMiningLaserInfo', 57 const.groupEnergyVampire: 'AddEnergyVampireInfo', 58 const.groupEnergyDestabilizer: 'AddEnergyDestabilizerInfo', 59 const.groupArmorRepairUnit: 'AddArmorRepairersInfo', 60 const.groupFueledArmorRepairer: 'AddArmorRepairersInfo', 61 const.groupFueledRemoteArmorRepairer: 'AddArmorRepairersInfo', 62 const.groupPrecursorRepairer: 'AddArmorRepairersInfo', 63 const.groupHullRepairUnit: 'AddHullRepairersInfo', 64 const.groupShieldBooster: 'AddShieldBoosterInfo', 65 const.groupFueledShieldBooster: 'AddShieldBoosterInfo', 66 const.groupTrackingComputer: 'AddTrackingComputerInfo', 67 const.groupTrackingLink: 'AddTrackingComputerInfo', 68 const.groupSmartBomb: 'AddSmartBombInfo', 69 const.groupPropulsionModule: 'AddPropulsionModuleInfo', 70 const.groupStasisWeb: 'AddStasisWebInfo', 71 const.groupWarpScrambler: 'AddWarpScramblerInfo', 72 const.groupCapacitorBooster: 'AddCapacitorBoosterInfo', 73 const.groupEnergyTransferArray: 'AddEnergyTransferArrayInfo', 74 const.groupShieldTransporter: 'AddShieldTransporterInfo', 75 const.groupArmorRepairProjector: 'AddArmorRepairProjectorInfo', 76 const.groupRemoteHullRepairer: 'AddRemoteHullRepairInfo', 77 const.groupArmorHardener: 'AddArmorHardenerInfo', 78 const.groupArmorCoating: 'AddArmorHardenerInfo', 79 const.groupShieldHardener: 'AddArmorHardenerInfo', 80 const.groupShieldAmplifier: 'AddArmorHardenerInfo', 81 const.groupArmorPlatingEnergized: 'AddArmorHardenerInfo', 82 const.groupElectronicCounterMeasureBurst: 'AddECMInfo', 83 const.groupElectronicCounterMeasures: 'AddECMInfo', 84 const.groupElectronicCounterCounterMeasures: 'AddECCMInfo', 85 const.groupProjectedElectronicCounterCounterMeasures: 'AddECCMInfo', 86 const.groupRemoteSensorDamper: 'AddSensorDamperInfo', 87 const.groupRemoteSensorBooster: 'AddSensorDamperInfo', 88 const.groupSensorBooster: 'AddSensorDamperInfo', 89 const.groupTargetBreaker: 'AddTargetBreakerInfo', 90 const.groupTargetPainter: 'AddTargetPainterInfo', 91 const.groupTrackingDisruptor: 'AddTrackingDisruptorInfo', 92 const.groupCloakingDevice: 'AddCloakingDeviceInfo', 93 const.groupTractorBeam: 'AddTractorBeamInfo', 94 const.groupDamageControl: 'AddDamageControlInfo', 95 const.groupArmorResistanceShiftHardener: 'AddArmorResistanceShiftHardenerInfo', 96 const.groupSuperWeapon: 'AddSuperWeaponInfo', 97 const.groupGangCoordinator: 'AddGangCoordinatorInfo', 98 const.groupScanProbeLauncher: 'AddScanProbeLauncherInfo', 99 const.groupCynosuralField: 'AddCynoInfo', 100 const.groupSiegeModule: 'AddSiegeInfo', 101 const.groupStructureStasisWebifier: 'AddStasisWebInfo', 102 const.groupStructureECM: 'AddECMInfo', 103 const.groupStructureWarpDisruptor: 'AddWarpScramblerInfo', 104 const.groupStructureEnergyNeutralizer: 'AddEnergyDestabilizerInfo', 105 const.groupStructureDefenseBattery: 'AddStructureDefenseBatteryInfo', 106 const.groupStructureDoomsdayWeapon: 'AddSuperWeaponInfo', 107 const.groupMissileLauncherDot: 'AddDotWeaponInfo', 108 const.groupPrecursorTurret: 'AddPrecursorTurretInfo'} 109 infoFunctionNamesForTypes = {const.typeStandupRemoteSensorDampener: 'AddSensorDamperInfo', 110 const.typeStandupWeaponDisruptor: 'AddTrackingDisruptorInfo', 111 const.typeStandupTargetPainter: 'AddTargetPainterInfo'} 112 113 def ApplyAttributes(self, attributes): 114 TooltipPanel.ApplyAttributes(self, attributes) 115 self.stateManager = sm.StartService('godma').GetStateManager() 116 self.dogmaLocation = sm.GetService('clientDogmaIM').GetDogmaLocation() 117 self.columns = 4 118 self.margin = 16 119 self.labelPadding = (4, 8, 4, 8) 120 self.cellSpacing = 0 121 self.cellPadding = 0 122 self.SetBackgroundAlpha(0.75) 123 self.controller = getattr(self.owner, 'controller', None) 124 125 def LoadTooltip(self): 126 if not self.owner: 127 return 128 self.ownerGuid = self.owner.__guid__ 129 if self.ownerGuid == 'xtriui.ModuleButton': 130 self.moduleItemID = self.owner.moduleinfo.itemID 131 else: 132 self.moduleItemID = self.controller.GetModuleID() 133 if not self.moduleItemID: 134 return 135 if self.ownerGuid in ('xtriui.FittingSlot', 'FittingServiceSlot', 'Drones'): 136 self.dogmaLocation = sm.GetService('fittingSvc').GetCurrentDogmaLocation() 137 else: 138 self.dogmaLocation = sm.GetService('clientDogmaIM').GetDogmaLocation() 139 self.moduleInfoItem = self.dogmaLocation.GetDogmaItem(self.moduleItemID) 140 self.moduleGroupID = evetypes.GetGroupID(self.moduleInfoItem.typeID) 141 self.moduleCategoryID = evetypes.GetCategoryID(self.moduleInfoItem.typeID) 142 self.numSlaves = self.GetNumberOfSlaves(self.moduleInfoItem, self.ownerGuid) 143 if self.stateManager.GetDefaultEffect(self.moduleInfoItem.typeID): 144 self.moduleShortcut = self.GetModuleShortcut(self.moduleInfoItem) 145 else: 146 self.moduleShortcut = None 147 self.typeName = evetypes.GetName(self.moduleInfoItem.typeID) 148 self.onHUDModuleButton = self.ownerGuid == 'xtriui.ModuleButton' 149 self.UpdateToolTips() 150 self._toolTooltipUpdateTimer = AutoTimer(1000, self.UpdateToolTips) 151 152 def UpdateToolTips(self): 153 if self.destroyed or self.beingDestroyed or self.owner is None: 154 self._toolTooltipUpdateTimer = None 155 return 156 self.Flush() 157 if getattr(self.owner, 'charge', None): 158 chargeItemID = self.owner.charge.itemID 159 elif self.controller and hasattr(self.controller, 'GetCharge') and self.controller.GetCharge(): 160 chargeItemID = self.controller.GetCharge().itemID 161 else: 162 chargeItemID = None 163 if chargeItemID is None: 164 chargeInfoItem = None 165 else: 166 chargeInfoItem = self.dogmaLocation.GetDogmaItem(chargeItemID) 167 moduleDamageInfo = self.GetModuleDamage(self.ownerGuid, self.moduleItemID) 168 chargesType, chargesQty = self.GetChargeTypeAndQty(self.moduleInfoItem, chargeInfoItem) 169 typeText = self.GetTypeText() 170 self.AddTypeAndIcon(label=typeText, typeID=self.moduleInfoItem.typeID, moduleShortcut=self.moduleShortcut, moduleDamageInfo=moduleDamageInfo) 171 self.UpdateChargesCont(chargeInfoItem, chargesQty) 172 maxRange, falloffDist, bombRadius, _ = self.GetRanges(chargeInfoItem) 173 if maxRange > 0: 174 self.AddRangeInfo(self.moduleInfoItem.typeID, optimalRange=maxRange, falloff=falloffDist) 175 if self.ShouldAddDps(chargesQty): 176 self.AddDpsAndDamgeTypeInfo(self.moduleItemID, self.moduleInfoItem.typeID, self.moduleGroupID, chargeInfoItem, self.numSlaves) 177 self.AddGroupAndCategoryExtraInfo(chargeInfoItem) 178 self.AddTrackingSpeed(self.moduleItemID) 179 self.AddCountDownTimes(self.moduleItemID) 180 if moduleDamageInfo.repairTimeLeft > 0: 181 self.GetTimeLeftRepairingCountDown(moduleDamageInfo.repairTimeLeft) 182 if self.onHUDModuleButton: 183 safetyLevel = self.owner.GetSafetyWarning() 184 if safetyLevel is not None: 185 self.AddSafetyLevelWarning(safetyLevel) 186 self.AddActivityStatus() 187 188 def AddGroupAndCategoryExtraInfo(self, chargeInfoItem): 189 categoryInfoFuncName = self.infoFunctionNamesForCategories.get(self.moduleCategoryID, None) 190 goupInfoFuncName = self.infoFunctionNames.get(self.moduleGroupID, None) 191 typeInfoFuncName = self.infoFunctionNamesForTypes.get(self.moduleInfoItem.typeID) 192 for funcName in (categoryInfoFuncName, goupInfoFuncName, typeInfoFuncName): 193 if funcName is None: 194 continue 195 myInfoFunction = getattr(self, funcName) 196 myInfoFunction(self.moduleItemID, chargeInfoItem) 197 198 def GetTypeText(self): 199 if self.numSlaves: 200 typeText = localization.GetByLabel('UI/Inflight/ModuleRacks/TypeNameWithNumInGroup', numInGroup=self.numSlaves, typeName=self.typeName) 201 else: 202 typeText = self.typeName 203 typeText = '<b>%s</b>' % typeText 204 return typeText 205 206 def GetRanges(self, chargeInfoItem): 207 return sm.GetService('tactical').FindMaxRange(self.moduleInfoItem, chargeInfoItem, self.dogmaLocation) 208 209 def ShouldAddDps(self, chargesQty): 210 shouldAddDps = chargesQty is not None 211 return shouldAddDps 212 213 def UpdateChargesCont(self, chargeInfoItem, chargesQty): 214 if chargeInfoItem and chargesQty: 215 chargeText = self.GetChargeText(chargeInfoItem, chargesQty) 216 self.AddTypeAndIcon(label=chargeText, typeID=chargeInfoItem.typeID) 217 218 def GetChargeText(self, chargeInfoItem, chargesQty): 219 if chargeInfoItem.groupID in cfg.GetCrystalGroups(): 220 crystalDamageAmount = self.GetCrystalDamage(chargeInfoItem) 221 chargeText = '<b>%s</b>' % evetypes.GetName(chargeInfoItem.typeID) 222 if crystalDamageAmount > 0.0: 223 damagedText = localization.GetByLabel('UI/Inflight/ModuleRacks/ModuleDamaged', color='<color=red>', percentageNum=crystalDamageAmount * 100) 224 chargeText += '<br>' + damagedText 225 else: 226 chargeText = localization.GetByLabel('UI/Inflight/ModuleRacks/AmmoNameWithQty', qty=chargesQty, ammoTypeID=chargeInfoItem.typeID) 227 return chargeText 228 229 def GetModuleDamage(self, ownerGuid, moduleItemID): 230 moduleDamageInfo = KeyVal(moduleDamage=None, repairingModuleDamage=None, repairTimeLeft=None) 231 myShipID = GetActiveShip() 232 if myShipID != self.dogmaLocation.GetCurrentShipID(): 233 return moduleDamageInfo 234 showSingleModuleReadout = ownerGuid in ('xtriui.FittingSlot', 'FittingServiceSlot') 235 if self.stateManager.IsBeingRepaired(moduleItemID): 236 repairingModuleDamage, repairTimeLeft = self.GetTotalDamageWhileRepairing(moduleItemID, showSingleModuleReadout) 237 moduleDamageInfo.repairingModuleDamage = int(math.ceil(repairingModuleDamage / self.dogmaLocation.GetAttributeValue(moduleItemID, const.attributeHp) * 100)) 238 moduleDamageInfo.repairTimeLeft = repairTimeLeft 239 else: 240 if showSingleModuleReadout: 241 damage = self.dogmaLocation.GetAccurateAttributeValue(moduleItemID, const.attributeDamage) 242 else: 243 damage = uicore.layer.shipui.controller.GetModuleGroupDamage(moduleItemID) 244 if damage: 245 moduleDamageAmount = int(math.ceil(damage / self.dogmaLocation.GetAttributeValue(moduleItemID, const.attributeHp) * 100)) 246 moduleDamageInfo.moduleDamage = moduleDamageAmount 247 return moduleDamageInfo 248 249 def GetCrystalDamage(self, chargeInfoItem): 250 crystalDamageAmount = None 251 if chargeInfoItem is not None: 252 if self.ownerGuid == 'xtriui.FittingSlot': 253 dogmaLocation = sm.GetService('fittingSvc').GetCurrentDogmaLocation() 254 else: 255 dogmaLocation = sm.GetService('clientDogmaIM').GetDogmaLocation() 256 crystalDamageAmount = dogmaLocation.GetAccurateAttributeValue(chargeInfoItem.itemID, const.attributeDamage) 257 return crystalDamageAmount 258 259 def GetNumberOfSlaves(self, moduleInfoItem, ownerGuid): 260 myShip = GetActiveShip() 261 if ownerGuid == 'xtriui.FittingSlot': 262 return 0 263 else: 264 slaves = self.dogmaLocation.GetSlaveModules(moduleInfoItem.itemID, myShip) 265 if slaves: 266 numSlaves = len(slaves) + 1 267 else: 268 numSlaves = 0 269 return numSlaves 270 271 def GetModuleShortcut(self, moduleInfoItem): 272 moduleShortcut = None 273 masterModuleID = self.dogmaLocation.GetMasterModuleID(GetActiveShip(), moduleInfoItem.itemID) 274 if masterModuleID is not None: 275 masterModuleInfoItem = self.dogmaLocation.GetDogmaItem(masterModuleID) 276 flagID = masterModuleInfoItem.flagID 277 else: 278 flagID = moduleInfoItem.flagID 279 slotOrder = shipHud.GetSlotOrder() 280 if flagID not in slotOrder: 281 return 282 pos = slotOrder.index(flagID) 283 if pos is not None: 284 row = pos / 8 285 hiMedLo = ('High', 'Medium', 'Low')[row] 286 loc = pos % 8 287 slotno = loc + 1 288 shortcut = uicore.cmd.GetShortcutStringByFuncName('CmdActivate%sPowerSlot%i' % (hiMedLo, slotno)) 289 if shortcut: 290 moduleShortcut = shortcut 291 return moduleShortcut 292 293 def GetChargeTypeAndQty(self, moduleInfoItem, chargeInfoItem): 294 chargesQty = None 295 chargesType = None 296 if self.IsChargeCompatible(moduleInfoItem): 297 if chargeInfoItem and chargeInfoItem.typeID: 298 chargesQty = self.dogmaLocation.GetQuantity(chargeInfoItem.itemID) 299 chargesType = chargeInfoItem.typeID 300 else: 301 chargesQty = 0 302 return (chargesType, chargesQty) 303 304 def IsChargeCompatible(self, moduleInfoItem): 305 return moduleInfoItem.groupID in cfg.__chargecompatiblegroups__ 306 307 def GetEffectiveAttributeValue(self, itemID, attributeID): 308 attributeValue = self.dogmaLocation.GetAccurateAttributeValue(itemID, attributeID) 309 unitID = dogma_data.get_attribute_unit_id(attributeID) 310 if unitID in (const.unitInverseAbsolutePercent, const.unitInversedModifierPercent): 311 attributeValue = (1.0 - attributeValue) * 100.0 312 elif unitID == const.unitModifierPercent: 313 attributeValue = -(1.0 - attributeValue) * 100.0 314 return attributeValue 315 316 def GetDuration(self, itemID, durationAttributeID = None): 317 if durationAttributeID is None: 318 durationAttributeID = const.attributeDuration 319 duration = self.GetEffectiveAttributeValue(itemID, durationAttributeID) 320 durationInSec = duration / 1000.0 321 return FormatSeconds(durationInSec) 322 323 def AddSafetyLevelWarning(self, safetyLevel): 324 if safetyLevel == const.shipSafetyLevelNone: 325 iconColor = CrimeWatchColors.Criminal.GetRGBA() 326 text = localization.GetByLabel('UI/Crimewatch/SafetyLevel/ModuleRestrictionTooltip', color=CrimeWatchColors.Criminal.GetHex()) 327 else: 328 iconColor = CrimeWatchColors.Suspect.GetRGBA() 329 text = localization.GetByLabel('UI/Crimewatch/SafetyLevel/ModuleRestrictionTooltip', color=CrimeWatchColors.Suspect.GetHex()) 330 texturePath = 'res:/UI/Texture/Crimewatch/Crimewatch_SuspectCriminal.png' 331 icon, label = self.AddRowWithIconAndText(text, texturePath, iconSize=16) 332 icon.SetRGBA(*iconColor) 333 334 def AddActivityStatus(self): 335 text, color, activityState = self.dogmaLocation.GetActivityState(self.moduleItemID) 336 if text: 337 self.FillRow() 338 self.AddCell(colSpan=2) 339 label = self.AddLabelLarge(text=text, colSpan=self.columns - 2, align=uiconst.CENTERLEFT, cellPadding=self.labelPadding, bold=True) 340 label.SetRGBA(*color) 341 342 def AddTypeAndIcon(self, label, typeID, moduleShortcut = None, moduleDamageInfo = None, iconSize = 26, minRowSize = 30): 343 self.FillRow() 344 self.AddSpacer(height=minRowSize, width=0) 345 iconCont = Container(pos=(0, 346 0, 347 iconSize, 348 iconSize), align=uiconst.CENTER) 349 iconObj = Icon(parent=iconCont, pos=(0, 350 0, 351 iconSize, 352 iconSize), align=uiconst.TOPLEFT, ignoreSize=True) 353 iconObj.LoadIconByTypeID(typeID, size=iconSize, ignoreSize=True) 354 techIcon = Icon(parent=iconCont, width=16, height=16, align=uiconst.TOPLEFT, idx=0, top=0) 355 GetTechLevelIcon(techIcon, typeID=typeID) 356 self.AddCell(iconCont, cellPadding=2) 357 if moduleShortcut: 358 nameColSpan = self.columns - 3 359 else: 360 nameColSpan = self.columns - 2 361 if moduleDamageInfo: 362 repairingText = '' 363 if moduleDamageInfo.repairingModuleDamage: 364 repairingText = localization.GetByLabel('UI/Inflight/ModuleRacks/Tooltips/ModuleRepairing') 365 damageToShow = moduleDamageInfo.repairingModuleDamage or moduleDamageInfo.moduleDamage 366 if damageToShow > 0: 367 damagedText = localization.GetByLabel('UI/Inflight/ModuleRacks/ModuleDamaged', color='<color=red>', percentageNum=damageToShow) 368 label += '<br>%s%s' % (damagedText, repairingText) 369 labelObj = self.AddLabelMedium(text=label, align=uiconst.CENTERLEFT, cellPadding=self.labelPadding, colSpan=nameColSpan) 370 if moduleShortcut: 371 shortcutObj = ShortcutHint(text=moduleShortcut) 372 shortcutObj.width += 10 373 shortcutObj.padLeft = 10 374 self.AddCell(shortcutObj) 375 return (iconObj, labelObj) 376 377 def AddAttributeRow(self, texturePath, attributeValues, minRowSize = 30, spacerWidth = 100): 378 self.AddCell() 379 self.AddCell() 380 self.AddSpacer(colSpan=self.columns - 2, width=spacerWidth, height=0) 381 self.FillRow() 382 self.AddSpacer(width=0, height=minRowSize) 383 self.AddIconCell(texturePath) 384 container = AttributeValueRowContainer(attributeValues=attributeValues) 385 self.AddCell(container, colSpan=self.columns - 2) 386 self.FillRow() 387 388 def AddRangeInfo(self, typeID, optimalRange, falloff): 389 text, formattedOptimalRange = self.GetOptimalRangeText(typeID, optimalRange, falloff) 390 if not text: 391 return 392 texturePath = 'res:/UI/Texture/Icons/22_32_15.png' 393 self.AddRowWithIconAndText(text, texturePath) 394 395 def GetOptimalRangeText(self, typeID, optimalRange, falloff): 396 if optimalRange <= 0: 397 return ('', '') 398 formattedOptimalRAnge = FmtDist(optimalRange) 399 if sm.GetService('clientDogmaStaticSvc').TypeHasEffect(typeID, const.effectLauncherFitted): 400 rangeText = localization.GetByLabel('UI/Inflight/ModuleRacks/MaxRange', maxRange=formattedOptimalRAnge) 401 elif sm.GetService('clientDogmaStaticSvc').TypeHasEffect(typeID, const.effectTurretFitted) or evetypes.GetCategoryID(typeID) == const.categoryFighter: 402 if falloff > 1: 403 rangeText = localization.GetByLabel('UI/Inflight/ModuleRacks/OptimalRangeAndFalloff', optimalRange=formattedOptimalRAnge, falloffPlusOptimal=FmtDist(falloff + optimalRange)) 404 else: 405 rangeText = localization.GetByLabel('UI/Inflight/ModuleRacks/OptimalRange', optimalRange=formattedOptimalRAnge) 406 elif evetypes.GetGroupID(typeID) == const.groupSmartBomb: 407 rangeText = localization.GetByLabel('UI/Inflight/ModuleRacks/AreaOfEffect', range=formattedOptimalRAnge) 408 elif falloff > 1: 409 rangeText = localization.GetByLabel('UI/Inflight/ModuleRacks/RangeWithFalloff', optimalRange=formattedOptimalRAnge, falloffPlusOptimal=FmtDist(falloff + optimalRange)) 410 else: 411 rangeText = localization.GetByLabel('UI/Inflight/ModuleRacks/Range', optimalRange=formattedOptimalRAnge) 412 return (rangeText, formattedOptimalRAnge) 413 414 def GetAmountPerTimeInfo(self, itemID, attributeID, labelPath, chargeMultiplier = 1.0): 415 duration = self.GetDuration(itemID) 416 amount = self.GetEffectiveAttributeValue(itemID, attributeID) 417 amount = amount * chargeMultiplier 418 text = localization.GetByLabel(labelPath, duration=duration, amount=amount) 419 return (text, duration, amount) 420 421 def AddRowWithIconAndText(self, text, texturePath = None, iconID = None, iconSize = 24, minRowSize = 30): 422 self.FillRow() 423 self.AddSpacer(height=minRowSize, width=0) 424 icon = self.AddIconCell(texturePath or iconID, iconSize=iconSize) 425 label = self.AddLabelMedium(text=text, colSpan=self.columns - 2, align=uiconst.CENTERLEFT, cellPadding=self.labelPadding) 426 self.FillRow() 427 return (icon, label) 428 429 def AddRowWithIconAndTextAndValue(self, text, valueText, texturePath, iconSize = 24, minRowSize = 30): 430 self.FillRow() 431 self.AddSpacer(height=minRowSize, width=0) 432 self.AddIconCell(texturePath, iconSize=iconSize) 433 self.AddLabelMedium(text=text, colSpan=1, align=uiconst.CENTERLEFT, cellPadding=self.labelPadding) 434 self.AddLabelMedium(text=valueText, align=uiconst.CENTERRIGHT, left=2) 435 self.FillRow() 436 437 def AddRowWithIconAndContainer(self, texturePath, container, iconSize = 24, minRowSize = 30): 438 self.FillRow() 439 self.AddSpacer(height=minRowSize, width=0) 440 self.AddIconCell(texturePath, iconSize=iconSize) 441 self.AddCell(container, colSpan=self.columns - 1) 442 443 def AddIconCell(self, texturePath = None, iconID = None, iconSize = 24): 444 icon = Icon(pos=(0, 445 0, 446 iconSize, 447 iconSize), align=uiconst.CENTER, ignoreSize=True, state=uiconst.UI_DISABLED, icon=texturePath or iconID) 448 self.AddCell(icon) 449 return icon 450 451 def AddRowForInfoWithOneOrMoreAttributes(self, attributeValues, oneAttributeText, manyAttributesText, headerText, texturePath = ''): 452 if len(attributeValues) == 1: 453 self.AddRowForSingleAttribute(attributeValues=attributeValues, labelPath=oneAttributeText) 454 elif attributeValues: 455 self.AddRowAndHeaderForManyAttributes(attributeValues, manyAttributesText, headerText, texturePath) 456 457 def AddRowForSingleAttribute(self, attributeValues, labelPath): 458 attributeID, value = attributeValues[0] 459 iconID = dogma_data.get_attribute_icon_id(attributeID) 460 displayName = dogma_data.get_attribute_display_name(attributeID) 461 text = localization.GetByLabel(labelPath, activeName=displayName, activeValue=value) 462 self.AddRowWithIconAndText(text=text, iconID=iconID) 463 464 def AddRowAndHeaderForManyAttributes(self, attributeValues, manyAttributesText, headerText, texturePath = ''): 465 text = localization.GetByLabel(headerText) 466 icon, label = self.AddRowWithIconAndText(text=text, texturePath='', minRowSize=24) 467 label.SetAlign(uiconst.BOTTOMLEFT) 468 formattedAttributeValues = self.GetFormattedAttributeValues(attributeValues=attributeValues, valueText=manyAttributesText) 469 self.AddAttributeRow(texturePath, formattedAttributeValues, minRowSize=0, spacerWidth=65 * len(formattedAttributeValues)) 470 471 def GetFormattedAttributeValues(self, attributeValues, valueText): 472 attributeValuesText = [] 473 for attributeID, attributeValue in attributeValues: 474 attributeValueText = localization.GetByLabel(valueText, activeValue=attributeValue) 475 attributeValuesText.append((attributeID, attributeValueText)) 476 477 return attributeValuesText 478 479 def AddDpsAndDamgeTypeInfo(self, itemID, typeID, groupID, charge, numSlaves): 480 dmgInfo = self.GetDpsDamageTypeInfo(itemID, typeID, groupID, charge, numSlaves) 481 if not dmgInfo: 482 return 483 if dmgInfo.totalMaxDpsDamage: 484 text = localization.GetByLabel('UI/Inflight/ModuleRacks/DamagePerSecondRange', dps=dmgInfo.totalDpsDamage, maxDps=dmgInfo.totalMaxDpsDamage) 485 else: 486 text = localization.GetByLabel('UI/Inflight/ModuleRacks/DamagePerSecond', dps=dmgInfo.totalDpsDamage) 487 self.AddRowWithIconAndText(text=text, texturePath=dmgInfo.texturePath, iconID=dmgInfo.iconID) 488 self.AddDamageTypes(itemID, charge, dmgInfo.damageMultiplier) 489 490 def GetDpsDamageTypeInfo(self, itemID, typeID, groupID, charge, numSlaves): 491 isBomb = groupID == const.groupMissileLauncherBomb 492 dogmaStaticSvc = sm.GetService('clientDogmaStaticSvc') 493 isLauncher = dogmaStaticSvc.TypeHasEffect(typeID, const.effectLauncherFitted) or dogmaStaticSvc.TypeHasEffect(typeID, const.effectUseMissiles) 494 isTurret = dogmaStaticSvc.TypeHasEffect(typeID, const.effectTurretFitted) 495 if not isLauncher and not isTurret and not isBomb: 496 return 497 GAV = self.dogmaLocation.GetAccurateAttributeValue 498 texturePath = None 499 iconID = None 500 totalDpsDamage = 0 501 totalDpsDamageWithReload = 0 502 totalMaxDpsDamage = None 503 totalMaxDpsDamageWithReload = None 504 damageMultiplier = 1 505 if (isLauncher or isBomb) and charge: 506 chargeKey = charge.itemID 507 damageMultiplier = GetMissleDamageMultiplier(self.dogmaLocation, itemID, session.charid, GAV) 508 totalDpsDamage, totalDpsDamageWithReload = GetLauncherDps(self.dogmaLocation, chargeKey, itemID, session.charid, GAV) 509 if isLauncher: 510 texturePath = 'res:/UI/Texture/Icons/81_64_16.png' 511 else: 512 iconID = evetypes.GetIconID(typeID) 513 elif isTurret: 514 if charge: 515 chargeKey = charge.itemID 516 else: 517 chargeKey = None 518 totalDpsDamage, totalDpsDamageWithReload, totalMaxDpsDamage, totalMaxDpsDamageWithReload = GetTurretDpsWithMax(self.dogmaLocation, chargeKey, itemID, GAV, False) 519 damageMultiplier = GAV(itemID, const.attributeDamageMultiplier) 520 damageMultiplier *= self.dogmaLocation.GetMaxDamageMultiplier(itemID) 521 texturePath = 'res:/UI/Texture/Icons/26_64_1.png' 522 if totalDpsDamage == 0: 523 return KeyVal(totalDpsDamage=totalDpsDamage, totalDpsDamageWithReload=totalDpsDamageWithReload, texturePath=texturePath, iconID=iconID, damageMultiplier=damageMultiplier, totalMaxDpsDamage=totalMaxDpsDamage, totalMaxDpsDamageWithReload=totalMaxDpsDamageWithReload) 524 if numSlaves: 525 totalDpsDamage = numSlaves * totalDpsDamage 526 damageMultiplier = numSlaves * damageMultiplier 527 totalDpsDamageWithReload = numSlaves * totalDpsDamageWithReload 528 if totalMaxDpsDamage: 529 totalMaxDpsDamage = numSlaves * totalMaxDpsDamage 530 totalMaxDpsDamageWithReload = numSlaves * totalMaxDpsDamageWithReload 531 return KeyVal(totalDpsDamage=totalDpsDamage, totalDpsDamageWithReload=totalDpsDamageWithReload, texturePath=texturePath, iconID=iconID, damageMultiplier=damageMultiplier, totalMaxDpsDamage=totalMaxDpsDamage, totalMaxDpsDamageWithReload=totalMaxDpsDamageWithReload) 532 533 def AddDamageTypes(self, itemID, charge, multiplier): 534 if charge: 535 dmgCausingItemID = charge.itemID 536 else: 537 dmgCausingItemID = itemID 538 damageAttributeValues = self.GetAttributesValues(dmgCausingItemID, multiplier, dogma_attr_groups.damage_type_attribute_ids, includeZeros=False) 539 if not damageAttributeValues: 540 return 541 self.AddRowForInfoWithOneOrMoreAttributes(attributeValues=damageAttributeValues, oneAttributeText='UI/Inflight/ModuleRacks/Tooltips/OneDamageTypeText', manyAttributesText='UI/Inflight/ModuleRacks/Tooltips/DamageHitpoints', headerText='UI/Inflight/ModuleRacks/Tooltips/DamageTypesHeader') 542 543 def GetAttributesValues(self, itemID, multiplier, attributeList, includeZeros = True): 544 attributeValues = [] 545 for eachAttributeID in attributeList: 546 attributeValue = self.GetEffectiveAttributeValue(itemID, eachAttributeID) 547 if not attributeValue and not includeZeros: 548 continue 549 attributeValue = attributeValue * multiplier 550 attributeValues.append((eachAttributeID, attributeValue)) 551 552 return attributeValues 553 554 def AddAttributePerTimeInfo(self, itemID, attributeID, labelPath, chargeMultiplier = 1.0): 555 text, duration, amount = self.GetAmountPerTimeInfo(itemID=itemID, attributeID=attributeID, labelPath=labelPath, chargeMultiplier=chargeMultiplier) 556 iconID = dogma_data.get_attribute_icon_id(attributeID) 557 self.AddRowWithIconAndText(text=text, iconID=iconID) 558 559 def AddAttributeInfo(self, itemID, attributeID, labelPath, labelKeyword, skipZeroValue = False): 560 value = self.GetEffectiveAttributeValue(itemID, attributeID) 561 if value == 0 and skipZeroValue: 562 return 563 tokenDict = {labelKeyword: value} 564 text = localization.GetByLabel(labelPath, **tokenDict) 565 iconID = dogma_data.get_attribute_icon_id(attributeID) 566 self.AddRowWithIconAndText(text=text, iconID=iconID) 567 568 def AddAttributeInfoWithAttributeName(self, itemID, attributeID, labelPath, skipZeroValue = False): 569 activeValue = self.GetEffectiveAttributeValue(itemID, attributeID) 570 if activeValue == 0 and skipZeroValue: 571 return 572 iconID = dogma_data.get_attribute_icon_id(attributeID) 573 displayName = dogma_data.get_attribute_display_name(attributeID) 574 text = localization.GetByLabel(labelPath, activeValue=activeValue, activeName=displayName) 575 self.AddRowWithIconAndText(text=text, iconID=iconID) 576 577 def AddCompressorInfo(self, itemID, *args): 578 self.FillRow() 579 self.AddSpacer() 580 texturePath = 'res:/UI/Texture/Classes/SkillPlan/infoIcon.png' 581 range = self.GetEffectiveAttributeValue(itemID, const.attributeMaxRange) 582 text = localization.GetByLabel('UI/Inflight/ModuleRacks/Tooltips/CompressorModuleInfo', range=FmtDist(range)) 583 self.AddIconCell(texturePath, iconSize=34) 584 self.AddLabelMedium(text=text, colSpan=2, align=uiconst.CENTERLEFT, cellPadding=self.labelPadding, wrapWidth=250) 585 self.FillRow() 586 587 def AddMiningLaserInfo(self, itemID, chargeInfoItem, *args): 588 duration = self.GetDuration(itemID) 589 amount = self.GetEffectiveAttributeValue(itemID, const.attributeMiningAmount) 590 durationInSec = self.GetEffectiveAttributeValue(itemID, const.attributeDuration) / 1000.0 591 amountPerSec = amount / durationInSec 592 text = localization.GetByLabel('UI/Inflight/ModuleRacks/Tooltips/MiningAmountPerTime2', duration=duration, amount=amount, amountPerSec=amountPerSec) 593 self.AddRowWithIconAndText(text=text, texturePath='res:/ui/texture/icons/23_64_5.png') 594 595 def AddEnergyVampireInfo(self, itemID, chargeInfoItem): 596 self.AddAttributePerTimeInfo(itemID=itemID, attributeID=const.attributePowerTransferAmount, labelPath='UI/Inflight/ModuleRacks/Tooltips/EnergyVampireAmountPerTime') 597 598 def AddEnergyDestabilizerInfo(self, itemID, chargeInfoItem): 599 self.AddAttributePerTimeInfo(itemID=itemID, attributeID=const.attributeEnergyNeutralizerAmount, labelPath='UI/Inflight/ModuleRacks/Tooltips/EnergDestabilizedPerTime') 600 601 def AddArmorRepairersInfo(self, itemID, chargeInfoItem): 602 if chargeInfoItem: 603 chargeMultiplier = self.GetEffectiveAttributeValue(itemID, const.attributeChargedArmorDamageMultiplier) 604 else: 605 chargeMultiplier = 1.0 606 self.AddAttributePerTimeInfo(itemID=itemID, attributeID=const.attributeArmorDamageAmount, labelPath='UI/Inflight/ModuleRacks/Tooltips/ArmorRepairedPerTime', chargeMultiplier=chargeMultiplier) 607 608 def AddHullRepairersInfo(self, itemID, chargeInfoItem): 609 self.AddAttributePerTimeInfo(itemID=itemID, attributeID=const.attributeStructureDamageAmount, labelPath='UI/Inflight/ModuleRacks/Tooltips/HullRepairedPerTime') 610 611 def AddShieldBoosterInfo(self, itemID, chargeInfoItem): 612 self.AddAttributePerTimeInfo(itemID=itemID, attributeID=const.attributeShieldBonus, labelPath='UI/Inflight/ModuleRacks/Tooltips/ShieldBonusPerTime') 613 614 def AddTrackingComputerInfo(self, itemID, chargeInfoItem): 615 self.AddAttributeInfo(itemID=itemID, attributeID=const.attributeFalloffBonus, labelPath='UI/Inflight/ModuleRacks/Tooltips/TrackingComputerFalloffBonus', labelKeyword='falloffBonus') 616 self.AddAttributeInfo(itemID=itemID, attributeID=const.attributeMaxRangeBonus, labelPath='UI/Inflight/ModuleRacks/Tooltips/TrackingComputerRangeBonus', labelKeyword='optimalRangeBonus') 617 self.AddAttributeInfo(itemID=itemID, attributeID=const.attributeTrackingSpeedBonus, labelPath='UI/Inflight/ModuleRacks/Tooltips/TrackingComputerTrackingBonus', labelKeyword='trackingSpeedBonus') 618 619 def AddSmartBombInfo(self, itemID, chargeInfoItem): 620 attrID = None 621 damage = 0 622 for attributeID in dogma_attr_groups.damage_type_attribute_ids: 623 damage = self.GetEffectiveAttributeValue(itemID, attributeID) 624 if damage > 0: 625 attrID = attributeID 626 break 627 628 attributeInfo = dogma_data.get_attribute(attrID) 629 damageType = dogma_data.get_attribute_display_name(attrID) 630 iconID = attributeInfo.iconID 631 text = localization.GetByLabel('UI/Inflight/ModuleRacks/Tooltips/SmartBombDamage', amount=damage, damageType=damageType) 632 self.AddRowWithIconAndText(text=text, iconID=iconID) 633 634 def AddPropulsionModuleInfo(self, itemID, chargeInfoItem): 635 myShipID = self.dogmaLocation.GetActiveShipID() 636 if self.dogmaLocation.locationName == DL_NAME_FITTING: 637 _, _, activityState = self.dogmaLocation.GetActivityState(self.moduleItemID) 638 maxVelocity = self.dogmaLocation.GetAccurateAttributeValue(myShipID, attributeMaxVelocity) 639 if activityState in (ACTIVE, OVERHEATED): 640 text = localization.GetByLabel('UI/Inflight/ModuleRacks/Tooltips/MaxVelocityWith', maxVelocity=maxVelocity) 641 else: 642 text = localization.GetByLabel('UI/Inflight/ModuleRacks/Tooltips/MaxVelocityWithout', maxVelocity=maxVelocity) 643 else: 644 speedFactor, speedBoostFactor = self._GetSpeedBoostForPropulsionModule(itemID) 645 currentMass = self.dogmaLocation.GetAccurateAttributeValue(myShipID, attributeMass) 646 godmaEffect = self._GetDefaultDogmaEffect(itemID, self.moduleInfoItem.typeID) 647 if godmaEffect.isActive: 648 maxVelocityWithBonus = self.dogmaLocation.GetAccurateAttributeValue(myShipID, attributeMaxVelocity) 649 myMaxVelocity = maxVelocityWithBonus / self._GetVelocityRatio(speedBoostFactor, speedFactor, currentMass) 650 else: 651 myMaxVelocity, activatedMass = self._GetMyMaxVelocityAndMassOnActivation(itemID, myShipID, currentMass) 652 maxVelocityWithBonus = myMaxVelocity * self._GetVelocityRatio(speedBoostFactor, speedFactor, activatedMass) 653 text = localization.GetByLabel('UI/Inflight/ModuleRacks/Tooltips/MaxVelocityWithAndWithoutPropulsion', maxVelocity=myMaxVelocity, maxVelocityWithBonus=maxVelocityWithBonus) 654 iconID = dogma_data.get_attribute_icon_id(attributeMaxVelocity) 655 self.AddRowWithIconAndText(text=text, iconID=iconID) 656 657 def _GetMyMaxVelocityAndMassOnActivation(self, propulsionItemID, myShipID, currentMass): 658 myMaxVelocity = self.dogmaLocation.GetAccurateAttributeValue(myShipID, attributeMaxVelocity) 659 typeBaseMass = self.dogmaLocation.GetAttributeValue(myShipID, attributeMass) 660 massAddition = self.dogmaLocation.GetAttributeValue(propulsionItemID, attributeMassAddition) 661 massFactor = currentMass / typeBaseMass 662 massOnActivation = massFactor * (typeBaseMass + massAddition) 663 shipItem = self.dogmaLocation.GetDogmaItem(myShipID) 664 fittedItems = shipItem.GetFittedItems() 665 for fittedModuleItemID, moduleItem in fittedItems.iteritems(): 666 if propulsionItemID == fittedModuleItemID: 667 continue 668 if moduleItem.groupID == groupPropulsionModule: 669 godmaEffect = self._GetDefaultDogmaEffect(fittedModuleItemID, moduleItem.typeID) 670 if godmaEffect.isActive: 671 speedFactor, speedBoostFactor = self._GetSpeedBoostForPropulsionModule(fittedModuleItemID) 672 massAddition = self.dogmaLocation.GetAttributeValue(fittedModuleItemID, attributeMassAddition) 673 massFactor = currentMass / typeBaseMass 674 massOnActivation = massFactor * (currentMass - massAddition) 675 myMaxVelocity = myMaxVelocity / self._GetVelocityRatio(speedBoostFactor, speedFactor, currentMass) 676 break 677 678 return (myMaxVelocity, massOnActivation) 679 680 def _GetDefaultDogmaEffect(self, itemID, typeID): 681 effectName = self.stateManager.GetDefaultEffect(typeID).effectName 682 godmaItem = self.dogmaLocation.godma.GetItem(itemID) 683 return godmaItem.effects[effectName] 684 685 def _GetVelocityRatio(self, speedBoostFactor, speedFactor, mass): 686 return 1 + speedBoostFactor * speedFactor * 0.01 / mass 687 688 def _GetSpeedBoostForPropulsionModule(self, moduleItemID): 689 speedFactor = self.GetEffectiveAttributeValue(moduleItemID, attributeSpeedFactor) 690 speedBoostFactor = self.GetEffectiveAttributeValue(moduleItemID, attributeSpeedBoostFactor) 691 return (speedFactor, speedBoostFactor) 692 693 def AddStasisWebInfo(self, itemID, chargeInfoItem): 694 attributeID = const.attributeSpeedFactor 695 amount = self.GetEffectiveAttributeValue(itemID, attributeID) 696 text = localization.GetByLabel('UI/Inflight/ModuleRacks/Tooltips/VelocityReductionFromWeb', percentage=abs(amount)) 697 iconID = dogma_data.get_attribute_icon_id(attributeID) 698 self.AddRowWithIconAndText(text=text, iconID=iconID) 699 700 def AddWarpScramblerInfo(self, itemID, chargeInfoItem): 701 self.AddAttributeInfo(itemID=itemID, attributeID=const.attributeWarpScrambleStrength, labelPath='UI/Inflight/ModuleRacks/Tooltips/WarpScramblerStrength', labelKeyword='strength') 702 703 def AddCapacitorBoosterInfo(self, itemID, chargeInfoItem): 704 attributeID = const.attributeCapacitorBonus 705 duration = self.GetDuration(itemID) 706 if chargeInfoItem is None: 707 return 708 amount = self.GetEffectiveAttributeValue(chargeInfoItem.itemID, attributeID) 709 text = localization.GetByLabel('UI/Inflight/ModuleRacks/Tooltips/CapacitorBoostPerTime', boostAmount=amount, duration=duration) 710 iconID = dogma_data.get_attribute_icon_id(attributeID) 711 self.AddRowWithIconAndText(text=text, iconID=iconID) 712 713 def AddEnergyTransferArrayInfo(self, itemID, chargeInfoItem): 714 self.AddAttributePerTimeInfo(itemID=itemID, attributeID=const.attributePowerTransferAmount, labelPath='UI/Inflight/ModuleRacks/Tooltips/EnergyTransferredPerTime') 715 716 def AddShieldTransporterInfo(self, itemID, chargeInfoItem): 717 self.AddAttributePerTimeInfo(itemID=itemID, attributeID=const.attributeShieldBonus, labelPath='UI/Inflight/ModuleRacks/Tooltips/ShieldTransportedPerTime') 718 719 def AddArmorRepairProjectorInfo(self, itemID, chargeInfoItem): 720 self.AddAttributePerTimeInfo(itemID=itemID, attributeID=const.attributeArmorDamageAmount, labelPath='UI/Inflight/ModuleRacks/Tooltips/ArmorTransferredPerTime') 721 722 def AddRemoteHullRepairInfo(self, itemID, chargeInfoItem): 723 self.AddAttributePerTimeInfo(itemID=itemID, attributeID=const.attributeStructureDamageAmount, labelPath='UI/Inflight/ModuleRacks/Tooltips/HullRemoteRepairedPerTime') 724 725 def AddArmorHardenerInfo(self, itemID, chargeInfoItem): 726 damageAttributeValues = self.GetAttributesValues(itemID, 1, RESISTANCE_BONUS_ATTRIBUTES, includeZeros=False) 727 self.AddRowForInfoWithOneOrMoreAttributes(attributeValues=damageAttributeValues, oneAttributeText='UI/Inflight/ModuleRacks/Tooltips/ResistanceActiveBonusText', manyAttributesText='UI/Inflight/ModuleRacks/Tooltips/ResistanceActiveBonusValues', headerText='UI/Inflight/ModuleRacks/Tooltips/ResistanceActiveBonusesHeader') 728 729 def AddECMInfo(self, itemID, chargeInfoItem): 730 bonusAttributes = [const.attributeScanGravimetricStrengthBonus, 731 const.attributeScanLadarStrengthBonus, 732 const.attributeScanMagnetometricStrengthBonus, 733 const.attributeScanRadarStrengthBonus] 734 rows = [] 735 for attrID in bonusAttributes: 736 strength = self.GetEffectiveAttributeValue(itemID, attrID) 737 if strength is not None and strength != 0: 738 attributeName = dogma_data.get_attribute_display_name(attrID) 739 rows.append(localization.GetByLabel('UI/Inflight/ModuleRacks/Tooltips/ECMStrengthBonus', strength=strength, attributeName=attributeName)) 740 741 text = '<br>'.join(rows) 742 self.AddRowWithIconAndText(text=text, texturePath='res:/UI/Texture/Icons/4_64_12.png') 743 744 def AddECCMInfo(self, itemID, chargeInfoItem): 745 damageTypeAttributes = [const.attributeScanGravimetricStrengthPercent, 746 const.attributeScanLadarStrengthPercent, 747 const.attributeScanMagnetometricStrengthPercent, 748 const.attributeScanRadarStrengthPercent] 749 rows = [] 750 for attrID in damageTypeAttributes: 751 strength = self.GetEffectiveAttributeValue(itemID, attrID) 752 if strength is not None and strength != 0: 753 attributeName = dogma_data.get_attribute_display_name(attrID) 754 rows.append(localization.GetByLabel('UI/Inflight/ModuleRacks/Tooltips/ValuePercentageWithAttributeName', activeValue=strength, activeName=attributeName)) 755 756 text = '<br>'.join(rows) 757 if text: 758 self.AddRowWithIconAndText(text=text, texturePath='res:/UI/Texture/Icons/4_64_12.png') 759 760 def AddSensorDamperInfo(self, itemID, chargeInfoItem): 761 bonus = self.GetEffectiveAttributeValue(itemID, const.attributeScanResolutionBonus) 762 if bonus != 0: 763 self.AddAttributeInfoWithAttributeName(itemID=itemID, attributeID=const.attributeScanResolutionBonus, labelPath='UI/Inflight/ModuleRacks/Tooltips/ValuePercentageWithAttributeName') 764 bonus = self.GetEffectiveAttributeValue(itemID, const.attributeMaxTargetRangeBonus) 765 if bonus != 0: 766 self.AddAttributeInfoWithAttributeName(itemID=itemID, attributeID=const.attributeMaxTargetRangeBonus, labelPath='UI/Inflight/ModuleRacks/Tooltips/ValuePercentageWithAttributeName') 767 self.AddECCMInfo(itemID, chargeInfoItem) 768 769 def AddTargetBreakerInfo(self, itemID, chargeInfoItem): 770 self.AddAttributeInfoWithAttributeName(itemID=itemID, attributeID=const.attributeSignatureSuppressorSignatureRadiusBonusPassive, labelPath='UI/Inflight/ModuleRacks/Tooltips/ValuePercentageWithAttributeName') 771 772 def AddTargetPainterInfo(self, itemID, chargeInfoItem): 773 self.AddAttributeInfoWithAttributeName(itemID=itemID, attributeID=const.attributeSignatureRadiusBonus, labelPath='UI/Inflight/ModuleRacks/Tooltips/ValuePercentageWithAttributeName') 774 775 def AddTrackingDisruptorInfo(self, itemID, chargeInfoItem): 776 self.AddAttributeInfoWithAttributeName(itemID=itemID, attributeID=const.attributeFalloffBonus, labelPath='UI/Inflight/ModuleRacks/Tooltips/ValuePercentageWithAttributeName', skipZeroValue=True) 777 self.AddAttributeInfoWithAttributeName(itemID=itemID, attributeID=const.attributeMaxRangeBonus, labelPath='UI/Inflight/ModuleRacks/Tooltips/ValuePercentageWithAttributeName', skipZeroValue=True) 778 self.AddAttributeInfoWithAttributeName(itemID=itemID, attributeID=const.attributeTrackingSpeedBonus, labelPath='UI/Inflight/ModuleRacks/Tooltips/ValuePercentageWithAttributeName', skipZeroValue=True) 779 self.AddAttributeInfoWithAttributeName(itemID=itemID, attributeID=const.attributeMissileVelocityBonus, labelPath='UI/Inflight/ModuleRacks/Tooltips/ValuePercentageWithAttributeName', skipZeroValue=True) 780 self.AddAttributeInfoWithAttributeName(itemID=itemID, attributeID=const.attributeExplosionDelayBonus, labelPath='UI/Inflight/ModuleRacks/Tooltips/ValuePercentageWithAttributeName', skipZeroValue=True) 781 self.AddAttributeInfoWithAttributeName(itemID=itemID, attributeID=const.attributeAoeVelocityBonus, labelPath='UI/Inflight/ModuleRacks/Tooltips/ValuePercentageWithAttributeName', skipZeroValue=True) 782 self.AddAttributeInfoWithAttributeName(itemID=itemID, attributeID=const.attributeAoeCloudSizeBonus, labelPath='UI/Inflight/ModuleRacks/Tooltips/ValuePercentageWithAttributeName', skipZeroValue=True) 783 784 def AddCloakingDeviceInfo(self, itemID, chargeInfoItem): 785 self.AddAttributeInfoWithAttributeName(itemID=itemID, attributeID=const.attributeMaxVelocityModifier, labelPath='UI/Inflight/ModuleRacks/Tooltips/ValuePercentageWithAttributeName') 786 787 def AddTractorBeamInfo(self, itemID, chargeInfoItem): 788 attributeID = const.attributeMaxTractorVelocity 789 maxTractorVel = self.GetEffectiveAttributeValue(itemID, attributeID) 790 iconID = dogma_data.get_attribute_icon_id(attributeID) 791 displayName = dogma_data.get_attribute_display_name(attributeID) 792 text = (localization.GetByLabel('UI/Inflight/ModuleRacks/Tooltips/TractorBeamTractorVelocity', maxTractorVel=maxTractorVel, attributeName=displayName),) 793 self.AddRowWithIconAndText(text=text, iconID=iconID) 794 795 def AddDamageControlInfo(self, itemID, chargeInfoItem): 796 shieldDamageTypeAttributes = [const.attributeShieldEmDamageResonance, 797 const.attributeShieldExplosiveDamageResonance, 798 const.attributeShieldKineticDamageResonance, 799 const.attributeShieldThermalDamageResonance] 800 armorDamageTypeAttributes = [const.attributeArmorEmDamageResonance, 801 const.attributeArmorExplosiveDamageResonance, 802 const.attributeArmorKineticDamageResonance, 803 const.attributeArmorThermalDamageResonance] 804 hullDamageTypeAttributes = [const.attributeHullEmDamageResonance, 805 const.attributeHullExplosiveDamageResonance, 806 const.attributeHullKineticDamageResonance, 807 const.attributeHullThermalDamageResonance] 808 for damageTypeAttributes, texturePath, headerText in ((shieldDamageTypeAttributes, 'res:/UI/Texture/Icons/1_64_13.png', 'UI/Inflight/ModuleRacks/Tooltips/ShieldDamageResistanceHeader'), (armorDamageTypeAttributes, 'res:/UI/Texture/Icons/1_64_9.png', 'UI/Inflight/ModuleRacks/Tooltips/ArmorDamageResistanceHeader'), (hullDamageTypeAttributes, 'res:/UI/Texture/Icons/2_64_12.png', 'UI/Inflight/ModuleRacks/Tooltips/HullDamageResistanceHeader')): 809 attributeValues = self.GetAttributesValues(itemID, 1, damageTypeAttributes, includeZeros=True) 810 self.AddRowAndHeaderForManyAttributes(attributeValues=attributeValues, manyAttributesText='UI/Inflight/ModuleRacks/Tooltips/ResistanceActiveBonusValues', headerText=headerText, texturePath=texturePath) 811 812 def AddArmorResistanceShiftHardenerInfo(self, itemID, chargeInfoItem): 813 damageTypeAttributes = [const.attributeArmorEmDamageResonance, 814 const.attributeArmorExplosiveDamageResonance, 815 const.attributeArmorKineticDamageResonance, 816 const.attributeArmorThermalDamageResonance] 817 attributeValues = self.GetAttributesValues(itemID, 1, damageTypeAttributes, includeZeros=True) 818 self.AddRowAndHeaderForManyAttributes(attributeValues=attributeValues, manyAttributesText='UI/Inflight/ModuleRacks/Tooltips/ResistanceActiveBonusValues', headerText='UI/Inflight/ModuleRacks/Tooltips/ArmorDamageResistanceHeader', texturePath='') 819 820 def AddSuperWeaponInfo(self, itemID, chargeInfoItem): 821 for attributeID in dogma_attr_groups.damage_type_attribute_ids: 822 damage = self.GetEffectiveAttributeValue(itemID, attributeID) 823 if damage == 0: 824 continue 825 self.AddAttributeInfoWithAttributeName(itemID=itemID, attributeID=attributeID, labelPath='UI/Inflight/ModuleRacks/Tooltips/SuperWeaponDamage') 826 827 self.AddDurationCountdownTimes(itemID) 828 829 def AddGangCoordinatorInfo(self, itemID, chargeInfoItem): 830 commandBonus = self.GetEffectiveAttributeValue(itemID, const.attributeCommandbonus) 831 if commandBonus != 0: 832 displayName = dogma_data.get_attribute_display_name(const.attributeCommandbonus) 833 text = localization.GetByLabel('UI/Inflight/ModuleRacks/Tooltips/GangCoordinatorCommandBonus', commandBonus=commandBonus, attributeName=displayName) 834 self.AddRowWithIconAndText(text=text, texturePath='') 835 maxGangModulesAttrName = dogma_data.get_attribute_name(const.attributeMaxGangModules) 836 if maxGangModulesAttrName in self.stateManager.GetAttributes(itemID): 837 maxGangModules = self.GetEffectiveAttributeValue(itemID, const.attributeMaxGangModules) 838 displayName = dogma_data.get_attribute_display_name(const.attributeMaxGangModules) 839 text = localization.GetByLabel('UI/Inflight/ModuleRacks/Tooltips/GangCoordinatorMaxCommandRelays', maxGangModules=maxGangModules, attributeName=displayName) 840 self.AddRowWithIconAndText(text=text, texturePath='') 841 842 def AddStructureDefenseBatteryInfo(self, itemID, chargeInfoItem): 843 self.AddDamageTypes(itemID, chargeInfoItem, 1) 844 845 def AddScanProbeLauncherInfo(self, itemID, chargeInfoItem): 846 if chargeInfoItem: 847 self.AddAttributeInfoWithAttributeName(itemID=chargeInfoItem.itemID, attributeID=const.attributeBaseSensorStrength, labelPath='UI/Inflight/ModuleRacks/Tooltips/ScanProbeSensorStrength') 848 849 def AddCynoInfo(self, itemID, chargInfoItem): 850 self.AddDurationCountdownTimes(itemID) 851 852 def AddSiegeInfo(self, itemID, chargInfoItem): 853 self.AddDurationCountdownTimes(itemID) 854 855 def AddDotWeaponInfo(self, itemID, chargeInfoItem): 856 if chargeInfoItem: 857 GAV = self.dogmaLocation.GetAccurateAttributeValue 858 dotMaxDamagePerTick = GetDotDps(chargeInfoItem.itemID, itemID, GAV) 859 text = localization.GetByLabel('UI/Inflight/ModuleRacks/DamagePerSecond', dps=dotMaxDamagePerTick) 860 self.AddRowWithIconAndText(text=text, iconID=appConst.iconBreacherPod) 861 attributeID = const.attributeDotDuration 862 durationText = self.GetDuration(chargeInfoItem.itemID, attributeID) 863 displayName = dogma_data.get_attribute_display_name(attributeID) 864 text = localization.GetByLabel('UI/Inflight/ModuleRacks/Tooltips/DotEffectDuration', attributeName=displayName, duration=durationText) 865 self.AddRowWithIconAndText(text=text, iconID=dogma_data.get_attribute_icon_id(attributeID)) 866 867 def AddTrackingSpeed(self, itemID): 868 self.AddAttributeInfoWithAttributeName(itemID=itemID, attributeID=const.attributeTrackingSpeed, labelPath='UI/Inflight/ModuleRacks/Tooltips/WeaponAccuracyScore', skipZeroValue=True) 869 870 def AddPrecursorTurretInfo(self, itemID, chargeInfoItem): 871 if self.dogmaLocation.locationName == DL_NAME_FITTING: 872 return 873 godmaEffect = self._GetDefaultDogmaEffect(itemID, self.moduleInfoItem.typeID) 874 if not godmaEffect.isActive: 875 return 876 damageMultiplierBonusMax = self.dogmaLocation.GetAccurateAttributeValue(itemID, const.attributeDamageMultiplierBonusMax) 877 current = self.dogmaLocation.GetAccurateAttributeValue(itemID, const.attributeDamageMultiplierBonusCurrent) 878 ratio = current / float(damageMultiplierBonusMax) 879 maxTimestamp = self.dogmaLocation.GetAccurateAttributeValue(itemID, const.attributeDamageMultiplierBonusMaxTimestamp) 880 if maxTimestamp: 881 timeUntilFullDmg = int(maxTimestamp - gametime.GetSimTime()) 882 self.FillRow() 883 if timeUntilFullDmg > 0: 884 timeText = FormatTimeIntervalShortWritten(timeUntilFullDmg, showFrom='minute') 885 timeUntilText = localization.GetByLabel('UI/Inflight/ModuleRacks/Tooltips/TimeUntilMaxDamage', time=timeText) 886 else: 887 timeUntilText = localization.GetByLabel('UI/Inflight/ModuleRacks/Tooltips/MaxDamage') 888 self.AddRowWithIconAndText(text=timeUntilText) 889 self.FillRow() 890 cont = Container(align=uiconst.TOTOP, height=30) 891 ratioText = localization.GetByLabel('UI/Common/Percentage', percentage=int(round(100 * ratio))) 892 ratioLabel = TextBody(parent=cont, text=ratioText, align=uiconst.CENTERRIGHT) 893 rowSize = max(ratioLabel.height + 4, 20) 894 gaugeHeight = 6 895 gaugeTop = (rowSize - gaugeHeight) / 2 896 cont.height = rowSize 897 gauge = Gauge(parent=cont, top=gaugeTop, gaugeHeight=gaugeHeight, align=uiconst.TOTOP, padLeft=3, padRight=max(ratioLabel.width + 8, 36), glowBrightness=0.1, color=THEME_ACCENT) 898 gauge.SetValue(ratio, animate=False) 899 self.AddRowWithIconAndContainer(texturePath='', container=cont, minRowSize=rowSize) 900 901 def AddCountDownTimes(self, itemID): 902 self._AddCountDownTimes(itemID, const.attributeModuleReactivationDelay, self.stateManager.GetCooldownTimes) 903 self._AddCountDownTimes(itemID, const.attributeReloadTime, self.stateManager.GetReloadTimes) 904 905 def AddDurationCountdownTimes(self, itemID): 906 self._AddCountDownTimes(itemID, const.attributeDuration, self._GetDurationTimeLeft) 907 908 def _AddCountDownTimes(self, itemID, attributeID, getTimeFunc): 909 if GetActiveShip() != self.dogmaLocation.GetCurrentShipID(): 910 return 911 itemCountdown = self.dogmaLocation.GetAccurateAttributeValue(itemID, attributeID) 912 if not itemCountdown: 913 return 914 coundDownTimes = getTimeFunc(itemID) 915 valueText = self._GetCountdownTime(coundDownTimes) 916 if not valueText: 917 return 918 text = dogma_data.get_attribute_display_name(attributeID) 919 self.AddRowWithIconAndTextAndValue(text=text, valueText=valueText, texturePath='') 920 921 def _GetCountdownTime(self, countdownTimes): 922 if countdownTimes is None: 923 return 924 startTime, delayTime = countdownTimes 925 now = gametime.GetSimTime() 926 finishTime = startTime + delayTime * const.MSEC 927 diff = finishTime - now 928 if diff < 0: 929 return 930 return FormatTimeIntervalShort(long(diff), showFrom='minute') 931 932 def _GetDurationTimeLeft(self, itemID): 933 return self.stateManager.GetDurationTimeLeft(itemID, self.moduleInfoItem.typeID) 934 935 def GetTimeLeftRepairingCountDown(self, timeLeft): 936 valueText = FormatTimeIntervalShort(long(timeLeft), showFrom='minute') 937 text = localization.GetByLabel('UI/Inflight/ModuleRacks/Tooltips/RepairTimeLeft') 938 self.AddRowWithIconAndTextAndValue(text=text, valueText=valueText, texturePath='') 939 940 def GetTotalDamageWhileRepairing(self, itemID, showSingleModuleReadout = True): 941 dogmaLocation = self.dogmaLocation 942 currentShipID = dogmaLocation.GetCurrentShipID() 943 masterID = dogmaLocation.IsInWeaponBank(currentShipID, itemID) 944 if masterID and not showSingleModuleReadout: 945 allModulesInBank = dogmaLocation.GetModulesInBank(currentShipID, masterID) 946 else: 947 allModulesInBank = [itemID] 948 maxDamage = 0 949 maxTimeLeft = 0 950 newNow = blue.os.GetSimTime() 951 rateOfRepairInMin = self.stateManager.GetAttribute(session.charid, 'moduleRepairRate') 952 rateOfRepair = const.MIN / rateOfRepairInMin 953 for eachModuleID in allModulesInBank: 954 repairStartTimeStamp = self.stateManager.GetRepairTimeStamp(eachModuleID) 955 if not repairStartTimeStamp: 956 continue 957 moduleDamage = dogmaLocation.GetAccurateAttributeValue(eachModuleID, const.attributeDamage) 958 repairTime = int(moduleDamage * rateOfRepair) 959 timeLeft = max(0, repairStartTimeStamp + repairTime - newNow) 960 damageLeftToRepair = timeLeft / float(repairTime) 961 currentDamgeOnModule = moduleDamage * damageLeftToRepair 962 maxDamage = max(currentDamgeOnModule, maxDamage) 963 maxTimeLeft = max(timeLeft, maxTimeLeft) 964 965 return (maxDamage, maxTimeLeft)