slotsContainer.py (30782B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\inflight\shipHud\slotsContainer.py 2 import random 3 import telemetry 4 import carbonui.const as uiconst 5 import evetypes 6 import uthread 7 from carbon.client.script.environment.AudioUtil import PlaySound 8 from carbon.common.script.util.timerstuff import AutoTimer 9 from carbonui.primitives.container import Container 10 from carbonui.uianimations import animations 11 from eve.client.script.ui.control.eveIcon import Icon 12 from eve.client.script.ui.control.eveLabel import EveLabelSmall 13 from eve.client.script.ui.inflight.moondefencebutton import DefenceStructureButton 14 from eve.client.script.ui.inflight.shipHud import GetSlotOrder 15 from eve.client.script.ui.inflight.shipHud.groupAllIcon import GroupAllButton 16 from eve.client.script.ui.inflight.shipHud.overloadBtn import OverloadBtn 17 from eve.client.script.ui.inflight.shipHud.shipSlot import ShipSlot 18 from eve.client.script.ui.inflight.shipModuleButton.shipmodulebutton import ModuleButton 19 from eve.client.script.ui.shared.fitting.fittingUtil import FITKEYS 20 from eve.common.script.sys.dbrow import LookupConstValue 21 from inventorycommon.util import IsShipFittingFlag 22 from localization import GetByLabel 23 from carbonui.uicore import uicore 24 import eve.client.script.ui.shared.pointerTool.pointerToolConst as pConst 25 from player_messaging.client.ui_message import prompt_player_fsd_dialog 26 from uihider import UiHiderMixin 27 ICONSIZE = 32 28 29 class SlotsContainer(UiHiderMixin, Container): 30 default_name = 'slotsContainer' 31 uniqueUiName = pConst.UNIQUE_NAME_MODULE_SLOTS 32 __notifyevents__ = ['OnMapShortcut', 33 'OnRestoreDefaultShortcuts', 34 'ProcessShipEffect', 35 'OnAttributes', 36 'OnWeaponGroupsChanged', 37 'OnRefreshModuleBanks'] 38 39 def ApplyAttributes(self, attributes): 40 super(SlotsContainer, self).ApplyAttributes(attributes) 41 sm.RegisterNotify(self) 42 self.invCookie = sm.GetService('inv').Register(self) 43 self.controller = attributes.controller 44 self.slotsByFlag = {} 45 self.slotsByOrder = {} 46 self.modulesByID = {} 47 self.checkingoverloadrackstate = 0 48 self.totalSlaves = 0 49 self.myHarpointFlags = [] 50 self.groupAllButton = None 51 52 def Close(self): 53 Container.Close(self) 54 sm.GetService('inv').Unregister(self.invCookie) 55 56 def AnimateReveal(self): 57 PlaySound('onboarding_ui_sfx_play') 58 self.opacity = 0 59 self.Show() 60 animations.BlinkIn(self, startVal=0.2, endVal=1.0, loops=3) 61 62 def Hide(self, *args): 63 super(SlotsContainer, self).Hide(*args) 64 self.opacity = 0 65 66 def Show(self, *args, **kwargs): 67 super(SlotsContainer, self).Show(*args, **kwargs) 68 self.opacity = 1.0 69 70 def GetPosFromFlag(self, slotFlag): 71 return self.slotsByFlag[slotFlag].sr.slotPos 72 73 def ChangeSlots(self, toFlag, fromFlag): 74 toModule = self.GetModuleType(toFlag) 75 fromModule = self.GetModuleType(fromFlag) 76 shift = uicore.uilib.Key(uiconst.VK_SHIFT) 77 if toModule and fromModule and toModule[0] == fromModule[0]: 78 self.LinkWeapons(toModule, fromModule, toFlag, fromFlag, merge=not shift) 79 if not sm.GetService('clientDogmaIM').GetDogmaLocation().IsModuleMaster(toModule[1], session.shipid): 80 self.SwapSlots(fromFlag, toFlag) 81 else: 82 self.SwapSlots(toFlag, fromFlag) 83 84 def SwapSlots(self, slotFlag1, slotFlag2): 85 module1 = self.GetModuleType(slotFlag1) 86 module2 = self.GetModuleType(slotFlag2) 87 shift = uicore.uilib.Key(uiconst.VK_SHIFT) 88 if shift and module1 is None and module2 is not None: 89 dogmaLocation = sm.GetService('clientDogmaIM').GetDogmaLocation() 90 if dogmaLocation.IsInWeaponBank(session.shipid, module2[1]): 91 moduleID = dogmaLocation.UngroupModule(session.shipid, module2[1]) 92 slotFlag2 = dogmaLocation.GetItem(moduleID).flagID 93 current = GetSlotOrder()[:] 94 flag1Idx = current.index(slotFlag1) 95 flag2Idx = current.index(slotFlag2) 96 current[flag1Idx] = slotFlag2 97 current[flag2Idx] = slotFlag1 98 all = settings.user.ui.Get('slotOrder', {}) 99 all[session.shipid] = current 100 settings.user.ui.Set('slotOrder', all) 101 self.InitSlots() 102 103 def LinkWeapons(self, master, slave, slotFlag1, slotFlag2, merge = False): 104 dogmaLocation = sm.GetService('clientDogmaIM').GetDogmaLocation() 105 groupID = evetypes.GetGroupID(master[0]) 106 areTurrets = groupID in const.dgmGroupableGroupIDs 107 slaves = dogmaLocation.GetSlaveModules(slave[1], session.shipid) 108 swapSlots = 0 109 if slaves: 110 swapSlots = 1 111 if not areTurrets: 112 prompt_player_fsd_dialog('CustomNotify', {'notify': GetByLabel('UI/Inflight/WeaponGroupingRule')}) 113 return 114 weaponLinked = dogmaLocation.LinkWeapons(session.shipid, master[1], slave[1], merge=merge) 115 if weaponLinked and swapSlots: 116 self.SwapSlots(slotFlag1, slotFlag2) 117 118 def GetModuleType(self, flag): 119 if flag not in self.slotsByFlag: 120 return None 121 module = self.slotsByFlag[flag].sr.module 122 if not module: 123 return None 124 return module.GetModuleType() 125 126 def GetModuleFromID(self, moduleID): 127 return self.modulesByID.get(moduleID, None) 128 129 def GetModule(self, moduleID): 130 return self.modulesByID.get(moduleID, None) 131 132 @telemetry.ZONE_METHOD 133 def InitDrawSlots(self, xstep, ystep, vgridrange, hgridrange, grid, myOrder, slotType = None): 134 for r in xrange(vgridrange): 135 x, y = grid[r] 136 for i in xrange(hgridrange): 137 slotFlag = myOrder[r * hgridrange + i] 138 if slotType == 'shipslot': 139 slot = ShipSlot(parent=self, pos=(0, 140 int(ystep * y), 141 64, 142 64), name='slot', state=uiconst.UI_HIDDEN, align=uiconst.TOPLEFT) 143 else: 144 slot = Container(name='defenceslot', parent=self, width=64, height=128 + 60, align=uiconst.TOPLEFT, state=uiconst.UI_HIDDEN, top=0) 145 slot.left = int((x + i) * xstep - 40) 146 slot.sr.module = None 147 slot.sr.slotFlag = slotFlag 148 slot.sr.slotPos = (r, i) 149 self.slotsByFlag[slotFlag] = slot 150 self.slotsByOrder[r, i] = slot 151 slot.sr.shortcutHint = EveLabelSmall(text='<center>-', parent=slot, width=64, color=(1.0, 1.0, 1.0, 0.25), shadowOffset=(0, 0), state=uiconst.UI_DISABLED, idx=0) 152 slot.sr.shortcutHint.top = 30 153 if self.controller.IsControllingTurret(): 154 slot.sr.shortcutHint.top -= 4 155 156 self.RefreshShortcuts() 157 158 def RefreshShortcuts(self): 159 for (r, i), slot in self.slotsByOrder.iteritems(): 160 hiMedLo = ('High', 'Medium', 'Low')[r] 161 slotno = i + 1 162 txt = uicore.cmd.GetShortcutStringByFuncName('CmdActivate%sPowerSlot%i' % (hiMedLo, slotno)) 163 if not txt: 164 txt = '_' 165 slot.sr.shortcutHint.text = '<center>' + txt 166 167 def OnMapShortcut(self, *blah): 168 self.RefreshShortcuts() 169 170 def OnRestoreDefaultShortcuts(self): 171 self.RefreshShortcuts() 172 173 def ProcessShipEffect(self, godmaStm, effectState): 174 dogmaLocation = sm.GetService('clientDogmaIM').GetDogmaLocation() 175 masterID = dogmaLocation.IsInWeaponBank(session.shipid, effectState.itemID) 176 if masterID: 177 module = self.GetModule(masterID) 178 else: 179 module = self.GetModule(effectState.itemID) 180 if module: 181 uthread.new(module.Update, effectState) 182 uthread.new(self.CheckOverloadRackBtnState) 183 184 def OnAttributes(self, ch): 185 for each in ch: 186 if each[0] != 'damage': 187 continue 188 masterID, damage = sm.GetService('godma').GetStateManager().GetMaxDamagedModuleInGroup(session.shipid, each[1].itemID) 189 module = self.GetModule(masterID) 190 if module is None: 191 continue 192 module.SetDamage(damage / module.moduleinfo.hp) 193 194 def OnInvChange(self, item, change): 195 if const.ixFlag in change or const.ixLocationID in change and item[const.ixItemID] in self.modulesByID: 196 if IsShipFittingFlag(item.flagID) or IsShipFittingFlag(change[const.ixFlag]): 197 uthread.new(self.InitSlotsDelayed) 198 199 def IsItemHere(self, rec): 200 return rec.locationID == session.shipid and rec.categoryID in (const.categoryModule, const.categoryStructureModule) and rec.flagID not in (const.flagCargo, const.flagDroneBay) 201 202 def InitStructureSlots(self): 203 currentControl = sm.GetService('pwn').GetCurrentControl() 204 shipmodules = [] 205 charges = {} 206 if currentControl: 207 for k, v in currentControl.iteritems(): 208 shipmodules.append(sm.services['godma'].GetItem(k)) 209 210 xstep = int(ICONSIZE * 2.0) 211 ystep = int(ICONSIZE * 1.35) 212 vgridrange = 1 213 hgridrange = 5 214 grid = [[1.0, 0.1]] 215 myOrder = [0, 216 1, 217 2, 218 3, 219 4] 220 for i, moduleInfo in enumerate(shipmodules): 221 if moduleInfo is None: 222 continue 223 myOrder[i] = moduleInfo.itemID 224 if moduleInfo.itemID in currentControl: 225 item = sm.services['godma'].GetItem(moduleInfo.itemID) 226 if item.groupID == const.groupMobileLaserSentry and len(item.modules): 227 charges[moduleInfo.itemID] = item.modules[0] 228 elif len(item.sublocations): 229 charges[moduleInfo.itemID] = item.sublocations[0] 230 231 self.InitDrawSlots(xstep, ystep, vgridrange, hgridrange, grid, myOrder, slotType='structure') 232 for moduleInfo in shipmodules: 233 if moduleInfo: 234 self._FitStructureSlot(moduleInfo, charges) 235 236 self.CheckButtonVisibility(3, ['hiSlots'], 5, myOrder) 237 238 @telemetry.ZONE_METHOD 239 def InitSlots(self, animate = False): 240 self.initSlotsDelayedTimer = None 241 if self.destroyed: 242 return 243 if animate: 244 self.AnimateModulesOut() 245 else: 246 self.Flush() 247 self.modulesByID = {} 248 self.totalSlaves = 0 249 self.passiveFiltered = [] 250 if self.controller.IsControllingTurret(): 251 self.InitStructureSlots() 252 else: 253 charges = {} 254 for charge in self.controller.GetCharges(): 255 charges[charge.flagID] = charge 256 if charge.stacksize == 0: 257 sm.services['godma'].LogError('InitSlots.no quantity', charge, charge.flagID) 258 259 for module in self.controller.GetModules(): 260 if module.categoryID == const.categoryCharge: 261 charges[module.flagID] = module 262 263 xstep = int(ICONSIZE * 1.6) 264 ystep = int(ICONSIZE * 1.4) 265 vgridrange = 3 266 hgridrange = 8 267 grid = [[1.0, 0.0], [1.5, 1.0], [1.0, 2.0]] 268 myOrder = GetSlotOrder() 269 self.InitDrawSlots(xstep, ystep, vgridrange, hgridrange, grid, myOrder, slotType='shipslot') 270 if not self.controller.IsControllingStructure(): 271 self.InitOverloadBtns() 272 self.InitGroupAllButtons() 273 dogmaLocation = sm.StartService('clientDogmaIM').GetDogmaLocation() 274 IsSlave = lambda itemID: dogmaLocation.IsModuleSlave(itemID, session.shipid) 275 for moduleInfo in self.controller.GetModules(): 276 if IsSlave(moduleInfo.itemID): 277 self.totalSlaves += 1 278 continue 279 self._FitSlot(moduleInfo, charges) 280 281 self.CheckButtonVisibility(0, ['hiSlots', 'medSlots', 'lowSlots'], None, myOrder) 282 if animate: 283 self.AnimateModulesIn() 284 285 def InitSlotsDelayed(self): 286 self.initSlotsDelayedTimer = AutoTimer(200, self.InitSlots) 287 288 def CloseSlots_Delayed(self, toClose): 289 self.closeSlotsDelayedTimer = None 290 for child in toClose: 291 child.Close() 292 293 def AnimateModulesOut(self): 294 toClose = self.children[:] 295 for module in self.modulesByID.itervalues(): 296 module.ShowOffline() 297 module.isInActiveState = False 298 299 maxDuration = 1.0 300 fadeTime = 0.1 301 for child in toClose: 302 child.opacity = 0.999 303 fadeDelay = (maxDuration - fadeTime) * random.random() 304 uicore.animations.FadeOut(child, duration=fadeTime, curveType=uiconst.ANIM_LINEAR, timeOffset=fadeDelay) 305 306 self.closeSlotsDelayedTimer = AutoTimer(maxDuration, self.CloseSlots_Delayed, toClose) 307 308 def AnimateModulesIn(self): 309 for child in self.children[:]: 310 if child.opacity < 1.0: 311 continue 312 child.opacity = 0 313 uicore.animations.FadeIn(child, duration=1.0, timeOffset=1.0, curveType=uiconst.ANIM_OVERSHOT) 314 315 @telemetry.ZONE_METHOD 316 def InitGroupAllButtons(self): 317 self.groupAllButton = GroupAllButton(parent=self, idx=0) 318 319 def CheckGroupAllButton(self): 320 if self.groupAllButton: 321 self.groupAllButton.CheckGroupAllButton() 322 323 @telemetry.ZONE_METHOD 324 def InitOverloadBtns(self): 325 overloadEffectsByRack = {} 326 modulesByRack = {} 327 for module in self.controller.GetModules(): 328 for key in module.effects.iterkeys(): 329 effect = module.effects[key] 330 if effect.effectID in (const.effectHiPower, const.effectMedPower, const.effectLoPower): 331 if effect.effectID not in modulesByRack: 332 modulesByRack[effect.effectID] = [] 333 modulesByRack[effect.effectID].append(module) 334 for key in module.effects.iterkeys(): 335 effect2 = module.effects[key] 336 if effect2.effectCategory == const.dgmEffOverload: 337 if effect.effectID not in overloadEffectsByRack: 338 overloadEffectsByRack[effect.effectID] = [] 339 overloadEffectsByRack[effect.effectID].append(effect2) 340 341 grid = [[13, 52], [20, 66], [13, 80]] 342 for i, each in enumerate(FITKEYS): 343 x, y = grid[i] 344 par = OverloadBtn(name='overloadBtn' + each, parent=self, left=x, top=y, fitKey=each, powerEffectID=getattr(const, 'effect%sPower' % each, None), activationID=None) 345 346 self.CheckOverloadRackBtnState() 347 348 def OverloadRackBtnMouseDown(self, btn, *args): 349 btn.top = btn.orgPos + 1 350 351 def OverloadRackBtnMouseUp(self, btn, *args): 352 btn.top = btn.orgPos 353 354 def OverloadRackBtnMouseExit(self, btn, *args): 355 btn.top = btn.orgPos 356 357 @telemetry.ZONE_METHOD 358 def CheckOverloadRackBtnState(self): 359 if self.controller.IsControllingTurret() or self.controller.IsControllingStructure(): 360 return 361 if self.destroyed or not self: 362 return 363 if self.checkingoverloadrackstate: 364 self.checkingoverloadrackstate = 2 365 return 366 self.checkingoverloadrackstate = 1 367 overloadEffectsByRack = {} 368 modulesByRack = {} 369 for module in self.controller.GetModules(): 370 for key in module.effects.iterkeys(): 371 effect = module.effects[key] 372 if effect.effectID in (const.effectHiPower, const.effectMedPower, const.effectLoPower): 373 if effect.effectID not in modulesByRack: 374 modulesByRack[effect.effectID] = [] 375 modulesByRack[effect.effectID].append(module) 376 for key in module.effects.iterkeys(): 377 effect2 = module.effects[key] 378 if effect2.effectCategory == const.dgmEffOverload: 379 if effect.effectID not in overloadEffectsByRack: 380 overloadEffectsByRack[effect.effectID] = [] 381 overloadEffectsByRack[effect.effectID].append(effect2) 382 383 i = 0 384 for each in FITKEYS: 385 btn = self.GetChild('overloadBtn' + each) 386 btn.activationID = None 387 btn.active = False 388 btn.children[0].LoadTexture('res:/UI/Texture/classes/ShipUI/overloadBtn%sOff.png' % each) 389 btn.hint = GetByLabel('UI/Inflight/OverloadRack') 390 btn.state = uiconst.UI_DISABLED 391 if btn.powerEffectID in modulesByRack: 392 btn.activationID = modulesByRack[btn.powerEffectID][0].itemID 393 if btn.powerEffectID in overloadEffectsByRack: 394 sumInactive = sum([ 1 for olEffect in overloadEffectsByRack[btn.powerEffectID] if not olEffect.isActive ]) 395 if not sumInactive: 396 btn.children[0].LoadTexture('res:/UI/Texture/classes/ShipUI/overloadBtn%sOn.png' % each) 397 btn.active = True 398 btn.hint = GetByLabel('UI/Inflight/StopOverloadingRack') 399 btn.state = uiconst.UI_NORMAL 400 401 if self.checkingoverloadrackstate == 2: 402 self.checkingoverloadrackstate = 0 403 return self.CheckOverloadRackBtnState() 404 self.checkingoverloadrackstate = 0 405 406 @telemetry.ZONE_METHOD 407 def CheckButtonVisibility(self, gidx, sTypes, totalslot, myOrder): 408 lastType = '' 409 showEmptySlots = settings.user.ui.Get('showEmptySlots', 0) 410 slotUIID = 0 411 totalslots = 0 412 ignoredSlots = 0 413 for sType in sTypes: 414 if totalslot is None: 415 totalslots = self.GetNumSlots(sType) 416 for sidx in xrange(totalslots): 417 if sidx == 8: 418 break 419 flagTypes = ['Hi', 420 'Med', 421 'Lo', 422 'Stuct'] 423 if not self.controller.IsControllingTurret(): 424 if gidx < len(flagTypes): 425 slotFlag = getattr(const, 'flag%sSlot%s' % (flagTypes[gidx], sidx), None) 426 slot = self.slotsByFlag.get(slotFlag, None) 427 else: 428 slotFlag = myOrder[sidx] 429 slot = self.slotsByFlag.get(slotFlag, None) 430 typeNames = ['High', 431 'Medium', 432 'Low', 433 'Stuct'] 434 slotUIID += 1 435 if gidx < len(typeNames): 436 currType = typeNames[gidx] 437 if currType != lastType: 438 slotUIID = 1 439 lastType = currType 440 if slot: 441 slot.name = 'inFlight%sSlot%s' % (typeNames[gidx], slotUIID) 442 if showEmptySlots and not self.controller.IsControllingTurret(): 443 if slot and slot.sr.module is None and slotFlag not in self.passiveFiltered: 444 slot.showAsEmpty = 1 445 if gidx == 0: 446 if ignoredSlots < self.totalSlaves: 447 ignoredSlots += 1 448 slot.ignored = 1 449 continue 450 slot.hint = [GetByLabel('UI/Inflight/EmptyHighSlot'), GetByLabel('UI/Inflight/EmptyMediumSlot'), GetByLabel('UI/Inflight/EmptyLowSlot')][gidx] 451 slot.state = uiconst.UI_NORMAL 452 iconpath = ['ui_8_64_11', 453 'ui_8_64_10', 454 'ui_8_64_9', 455 'ui_44_64_14'][gidx] 456 icon = Icon(icon=iconpath, parent=slot, pos=(13, 13, 24, 24), align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED, idx=0, ignoreSize=True) 457 icon.left = (slot.width - icon.width) / 2 458 icon.opacity = 0.25 459 460 gidx += 1 461 462 def GetNumSlots(self, slotType): 463 if slotType == 'hiSlots': 464 return self.controller.GetNumHiSlots() 465 if slotType == 'medSlots': 466 return self.controller.GetNumMedSlots() 467 if slotType == 'lowSlots': 468 return self.controller.GetNumLowSlots() 469 470 def _FitStructureSlot(self, moduleInfo, charges): 471 showPassive = settings.user.ui.Get('showPassiveModules', 1) 472 if moduleInfo.categoryID != const.categoryStarbase: 473 return 474 if not showPassive and self.GetDefaultEffect(moduleInfo) is None: 475 self.passiveFiltered.append(moduleInfo.flagID) 476 return 477 slot = self.slotsByFlag.get(moduleInfo.itemID, None) 478 if slot is None: 479 return 480 if slot.sr.module is not None: 481 return 482 self.FitStructureSlot(slot, moduleInfo, charges.get(moduleInfo.itemID, None)) 483 484 @telemetry.ZONE_METHOD 485 def _FitSlot(self, moduleInfo, charges, grey = 0, slotUIID = 'slot'): 486 showPassive = settings.user.ui.Get('showPassiveModules', 1) 487 if moduleInfo.categoryID == const.categoryCharge: 488 return 489 if not showPassive and self.GetDefaultEffect(moduleInfo) is None: 490 self.passiveFiltered.append(moduleInfo.flagID) 491 return 492 slot = self.slotsByFlag.get(moduleInfo.flagID, None) 493 if slot is None: 494 return 495 if slot.sr.module is not None: 496 return 497 self.FitSlot(slot, moduleInfo, charges.get(moduleInfo.flagID, None), grey=grey, slotUIID=slotUIID) 498 499 def GetDefaultEffect(self, moduleInfo): 500 for key in moduleInfo.effects.iterkeys(): 501 effect = moduleInfo.effects[key] 502 if self.IsEffectActivatible(effect): 503 return effect 504 505 def IsEffectActivatible(self, effect): 506 return effect.isDefault and effect.effectName != 'online' and effect.effectCategory in (const.dgmEffActivation, const.dgmEffTarget) 507 508 def FitSlot(self, slot, moduleInfo, charge = None, grey = 0, slotUIID = 'slot'): 509 pos = (slot.width - 48) / 2 510 module = ModuleButton(name='ModuleButton_%s' % moduleInfo.typeID, parent=slot, align=uiconst.TOPLEFT, width=48, height=48, top=pos, left=pos, idx=0, state=uiconst.UI_NORMAL) 511 module.Setup(moduleInfo, grey=grey) 512 self.modulesByID[moduleInfo.itemID] = module 513 slot.sr.module = module 514 slot.state = uiconst.UI_NORMAL 515 slot.sr.shortcutHint.state = uiconst.UI_HIDDEN 516 slot.name = slotUIID 517 if charge: 518 module.SetCharge(charge) 519 if moduleInfo.flagID in [const.flagHiSlot0, 520 const.flagHiSlot1, 521 const.flagHiSlot2, 522 const.flagHiSlot3, 523 const.flagHiSlot4, 524 const.flagHiSlot5, 525 const.flagHiSlot6, 526 const.flagHiSlot7]: 527 self.myHarpointFlags.append(moduleInfo.flagID) 528 529 def FitStructureSlot(self, slot, moduleInfo, charge = None): 530 pos = (slot.width - 48) / 2 531 module = DefenceStructureButton(parent=slot, align=uiconst.TOPLEFT, width=64, height=250, top=0, left=0, idx=1, state=uiconst.UI_DISABLED) 532 module.Setup(moduleInfo) 533 self.modulesByID[moduleInfo.itemID] = module 534 slot.sr.module = module 535 slot.state = uiconst.UI_NORMAL 536 if charge: 537 module.SetCharge(charge) 538 539 def OnReloadAmmo(self): 540 modulesByCharge = {} 541 for module in self.modulesByID.itervalues(): 542 if not cfg.IsChargeCompatible(module.moduleinfo): 543 continue 544 chargeTypeID, chargeQuantity, roomForReload = module.GetChargeReloadInfo() 545 if chargeTypeID in modulesByCharge: 546 modulesByCharge[chargeTypeID].append(module) 547 else: 548 modulesByCharge[chargeTypeID] = [module] 549 550 dogmaLocation = sm.GetService('clientDogmaIM').GetDogmaLocation() 551 for chargeTypeID, modules in modulesByCharge.iteritems(): 552 ammoList = {} 553 for typeID, ammoInfo in dogmaLocation.GetMatchingAmmo(session.shipid, modules[0].moduleinfo.itemID).iteritems(): 554 if typeID != chargeTypeID: 555 continue 556 for item in ammoInfo.singletons: 557 ammoList[item.itemID] = item.stacksize 558 559 for item in ammoInfo.nonSingletons: 560 ammoList[item.itemID] = item.stacksize 561 562 for module in modules: 563 maxItemID = 0 564 chargeTypeID, chargeQuantity, roomForReload = module.GetChargeReloadInfo() 565 bestItemID = None 566 for itemID, quant in ammoList.iteritems(): 567 if quant >= roomForReload: 568 if not bestItemID or quant < ammoList[bestItemID]: 569 bestItemID = itemID 570 if not maxItemID or quant > ammoList[maxItemID]: 571 maxItemID = itemID 572 573 bestItemID = bestItemID or maxItemID 574 if bestItemID: 575 quant = min(roomForReload, ammoList[maxItemID]) 576 uthread.new(module.AutoReload, 1, bestItemID, quant) 577 ammoList[bestItemID] -= quant 578 579 def BlinkButton(self, key): 580 btn = self.sr.Get(key.lower(), None) or self.sr.Get('%sBtn' % key.lower(), None) 581 if not btn: 582 for each in self.modulesByID: 583 if getattr(each, 'locationFlag', None) == LookupConstValue('flag%s' % key, 'no'): 584 btn = each 585 break 586 587 if not btn: 588 return 589 if hasattr(btn.sr, 'icon'): 590 sm.GetService('ui').BlinkSpriteA(btn.sr.icon, 1.0, 1000, None, passColor=0) 591 else: 592 sm.GetService('ui').BlinkSpriteA(btn, 1.0, 1000, None, passColor=0) 593 594 def ChangeOpacityForRange(self, currentRange, *args): 595 curveSet = None 596 for module in self.modulesByID.itervalues(): 597 maxRange, falloffDist, bombRadius, _ = sm.GetService('tactical').FindMaxRange(module.moduleinfo, module.charge) 598 if maxRange == 0: 599 continue 600 animationDuration = 0.1 601 if currentRange <= maxRange + falloffDist: 602 if round(module.opacity, 3) != 1.5: 603 curveSet = uicore.animations.MorphScalar(module, 'opacity', startVal=module.opacity, endVal=1.5, duration=animationDuration, curveSet=curveSet) 604 elif round(module.opacity, 3) != 1.0: 605 curveSet = uicore.animations.MorphScalar(module, 'opacity', startVal=module.opacity, endVal=1.0, duration=animationDuration, curveSet=curveSet) 606 607 def ResetModuleButtonOpacity(self, *args): 608 for module in self.modulesByID.itervalues(): 609 module.StopAnimations() 610 module.opacity = 1.0 611 612 def ProcessPendingOverloadUpdate(self, moduleIDs): 613 for moduleID in moduleIDs: 614 moduleButton = self.modulesByID.get(moduleID, None) 615 if moduleButton is not None: 616 moduleButton.UpdateOverloadState() 617 618 def ResetSwapMode(self): 619 for each in self.children: 620 each.opacity = 1.0 621 if each.sr.get('module', -1) == -1: 622 continue 623 if each.sr.module is None and not getattr(each, 'showAsEmpty', 0) or getattr(each, 'ignored', 0): 624 each.state = uiconst.UI_HIDDEN 625 if getattr(each.sr, 'module', None): 626 if getattr(each, 'linkDragging', None): 627 each.linkDragging = 0 628 each.sr.module.CheckOverload() 629 each.sr.module.CheckOnline() 630 each.sr.module.CheckMasterSlave() 631 each.sr.module.StopShowingGroupHighlight() 632 each.sr.module.CheckOnline() 633 each.sr.module.blockClick = 0 634 635 def OnWeaponGroupsChanged(self): 636 uthread.new(self.InitSlots) 637 638 def OnRefreshModuleBanks(self): 639 uthread.new(self.InitSlots) 640 641 def GetModuleForFKey(self, key): 642 slot = int(key[1:]) 643 gidx = (slot - 1) / 8 644 sidx = (slot - 1) % 8 645 slot = self.slotsByOrder.get((gidx, sidx), None) 646 if slot and slot.sr.module and slot.sr.module.state == uiconst.UI_NORMAL: 647 return slot.sr.module 648 649 def OnF(self, sidx, gidx): 650 slot = self.slotsByOrder.get((gidx, sidx), None) 651 if slot and slot.sr.module and slot.sr.module.state == uiconst.UI_NORMAL: 652 uthread.new(slot.sr.module.Click) 653 else: 654 uthread.new(prompt_player_fsd_dialog, 'Disabled') 655 656 def OnFKeyOverload(self, sidx, gidx): 657 slot = self.slotsByOrder.get((gidx, sidx), None) 658 if slot and slot.sr.module and slot.sr.module.state == uiconst.UI_NORMAL: 659 if hasattr(slot.sr.module, 'ToggleOverload'): 660 uthread.new(slot.sr.module.ToggleOverload) 661 else: 662 uthread.new(prompt_player_fsd_dialog, 'Disabled') 663 664 def ToggleRackOverload(self, slotName): 665 if slotName not in FITKEYS or self.destroyed or self.controller.IsControllingStructure(): 666 return 667 btn = self.FindChild('overloadBtn' + slotName) 668 if btn: 669 if btn.activationID: 670 uthread.new(btn.OnClick) 671 else: 672 uthread.new(prompt_player_fsd_dialog, 'Disabled') 673 674 def StartDragMode(self, itemID, typeID): 675 for slot in self.children: 676 if not hasattr(slot, 'sr') or not hasattr(slot.sr, 'module'): 677 continue 678 if slot.name.startswith('overload') or slot.name == 'groupAllIcon': 679 continue 680 if slot.sr.module is None: 681 slot.opacity = 0.7 682 slot.state = uiconst.UI_NORMAL 683 if typeID is None: 684 continue 685 if getattr(slot.sr, 'module', None) is not None: 686 moduleType = slot.sr.module.GetModuleType() 687 isGroupable = slot.sr.module.moduleinfo.groupID in const.dgmGroupableGroupIDs 688 if isGroupable: 689 slot.linkDragging = 1 690 if slot.sr.module.moduleinfo.itemID == itemID: 691 slot.sr.module.icon.SetAlpha(0.2) 692 continue 693 elif moduleType and moduleType[0] == typeID: 694 slot.sr.module.ShowGroupHighlight() 695 696 def ToggleShowPassive(self): 697 settings.user.ui.Set('showPassiveModules', not settings.user.ui.Get('showPassiveModules', 1)) 698 self.InitSlots() 699 700 def ToggleShowEmpty(self): 701 settings.user.ui.Set('showEmptySlots', not settings.user.ui.Get('showEmptySlots', 0)) 702 self.InitSlots()