lpOfferEntry.py (19059B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\station\loyaltyPointStore\lpOfferEntry.py 2 import evetypes 3 import localization 4 import logging 5 import trinity 6 import uthread 7 import utillib 8 from carbonui import uiconst 9 from carbonui.control.button import Button 10 from carbonui.button.const import HEIGHT_NORMAL 11 from carbonui.control.scrollentries import SE_BaseClassCore 12 from carbonui.control.singlelineedits.singleLineEditInteger import SingleLineEditInteger 13 from carbonui.primitives.container import Container 14 from carbonui.primitives.containerAutoSize import ContainerAutoSize 15 from carbonui.primitives.sprite import Sprite 16 from carbonui.uicore import uicore 17 from carbonui.util.color import Color 18 from signals import Signal 19 from dogma import const as dogmaconst 20 from eve.client.script.ui.control import eveIcon 21 from eve.client.script.ui.control.eveIcon import OwnerIcon 22 from eve.client.script.ui.control.infoIcon import InfoIcon 23 from eve.client.script.ui.control.utilMenu import ExpandedUtilMenu 24 from shipcosmetics.common.const import CosmeticsType 25 from cosmetics.common.cosmeticsConst import BACKGROUND_PATH_BY_TYPE 26 from shipcosmetics.client.licensegateway.licenseSignals import on_ship_cosmetics_license_change 27 from eve.client.script.ui.station.loyaltyPointStore.lpLabels import LPStoreEntryLabel 28 from eve.client.script.ui.station.loyaltyPointStore.lpUtil import GetItemText 29 from eve.client.script.ui.station.lpstoreRequirement import getContainerName, getLabelName 30 from eve.common.lib import appConst 31 from inventorycommon import const as invconst 32 from localization import GetByLabel 33 logger = logging.getLogger(__name__) 34 35 class LPOfferEntry(SE_BaseClassCore): 36 __guid__ = 'listentry.LPOffer' 37 iconSize = 64 38 iconMargin = 2 39 lineHeight = 1 40 labelMargin = 6 41 entryHeight = 88 42 43 def ApplyAttributes(self, attributes): 44 self.godma = sm.GetService('godma') 45 self.lpSvc = sm.GetService('lpstore') 46 self.node = attributes.node 47 self.typeID = self.node.typeID 48 self.qty = self.node.Get('qty', 1) 49 self.reqItems = self.node.Get('reqItems', []) 50 self.lootItems = self.node.Get('lootItems', []) 51 self.lpOfferRequirementColumns = self.lpSvc.GetRequirements(self.node.corpID) 52 self.requiredStandings = self.node.Get('requiredStandings', None) 53 SE_BaseClassCore.ApplyAttributes(self, attributes) 54 self.amountEdit = None 55 self._AddRewardColumn() 56 self._AddRequirementColumns() 57 if self.requiredStandings: 58 self._AddStandingsColumn() 59 self.AddBuyButton() 60 61 def _AddRewardColumn(self): 62 self.sr.rewardParent = Container(parent=self, name='rewardParent', align=uiconst.TOLEFT, state=uiconst.UI_PICKCHILDREN) 63 self.sr.rewardIconParent = Container(parent=self.sr.rewardParent, name='rewardIconParent', align=uiconst.TOLEFT, width=self.entryHeight, padright=self.labelMargin) 64 self.sr.rewardInfoIcon = InfoIcon(parent=self.sr.rewardIconParent, align=uiconst.TOPRIGHT, left=10, top=10) 65 self.CreateIcon() 66 self.AddRewardLabel() 67 68 def CreateIcon(self): 69 self.sr.icon = eveIcon.Icon(name='logoIcon', parent=self.sr.rewardIconParent, size=self.iconSize, ignoreSize=True, align=uiconst.CENTER, state=uiconst.UI_DISABLED) 70 71 def _AddRequirementColumns(self): 72 for requirement in self.lpOfferRequirementColumns: 73 self._AddRequirementColumn(requirement) 74 75 def _AddRequirementColumn(self, requirement): 76 parentContainerName = getContainerName(requirement) 77 labelName = getLabelName(requirement) 78 notFulfilledHintPath = requirement.notFulfilledHintPath 79 parentContainer = Container(name=parentContainerName, parent=self, state=uiconst.UI_PICKCHILDREN, align=uiconst.TOLEFT, clipChildren=True) 80 label = LPStoreEntryLabel(parent=parentContainer, name=labelName, left=self.labelMargin, align=uiconst.CENTERLEFT, color=self.GetRowContentTint(), opacity=0.7 if self.node.isOwned else 1.0) 81 self.sr[labelName] = label 82 if notFulfilledHintPath: 83 self.sr[labelName].hint = localization.GetByLabel(notFulfilledHintPath) 84 85 def GetRowContentTint(self): 86 return LPStoreEntryLabel.default_color 87 88 def _AddStandingsColumn(self): 89 ownerID = self.requiredStandings['ownerID'] 90 standingsValue = self.requiredStandings['value'] 91 container = Container(name='requiredStandingsParent', parent=self, align=uiconst.TOLEFT, clipChildren=True) 92 standingsLabel = LPStoreEntryLabel(parent=container, name='requiredStandingsLabel', state=uiconst.UI_NORMAL, align=uiconst.CENTERLEFT, left=self.labelMargin, text=u'{:6.2f}'.format(standingsValue)) 93 standingsLabel.hint = localization.GetByLabel('UI/Standings/Restricted', from_id=ownerID, to_id=session.charid, required_standing=standingsValue, current_standing=sm.GetService('standing').GetStandingWithSkillBonus(ownerID, session.charid)) 94 if not self.lpSvc.IsStandingsFulfilled(self.node): 95 standingsLabel.color = Color.RED 96 OwnerIcon(parent=container, name='requiredStandingsIcon', align=uiconst.CENTERLEFT, left=standingsLabel.width + 8, size=36, width=36, height=36, ownerID=ownerID) 97 98 def AddRewardLabel(self): 99 self.sr.rewardLabel = LPStoreEntryLabel(parent=self.sr.rewardParent, align=uiconst.TOTOP, padTop=4, maxLines=3) 100 101 def AddBuyButton(self): 102 buyBtnCont = Container(parent=self.sr.rewardParent, name='buyBtnCont', state=uiconst.UI_PICKCHILDREN, align=uiconst.TOTOP, height=HEIGHT_NORMAL, padTop=4) 103 self.sr.buyBtn = Button(name='buyBtn', parent=buyBtnCont, label=localization.GetByLabel('UI/VirtualGoodsStore/Buttons/Buy'), align=uiconst.TOLEFT, func=self.OnBuyBtn) 104 105 def OnBuyBtn(self, *_args): 106 self.utilMenu = ExpandedUtilMenu(parent=uicore.layer.utilmenu, controller=self.sr.buyBtn, menuAlign=uiconst.TOPLEFT, GetUtilMenu=self.GetUtilMenu) 107 108 def GetUtilMenu(self, menuParent): 109 cont = ContainerAutoSize(parent=menuParent, align=uiconst.TOTOP, padding=appConst.defaultPadding) 110 cont.GetEntryWidth = lambda mc = cont: 80 111 self.amountEdit = SingleLineEditInteger(name='amountEdit', parent=cont, align=uiconst.TOTOP, minValue=1, maxValue=appConst.maxLoyaltyStoreBulkOffers, setvalue=1, label=localization.GetByLabel('UI/Common/Amount'), padding=(5, 10, 5, 0), OnReturn=self.Buy) 112 Button(name='buyButton', parent=cont, align=uiconst.TOTOP, label=localization.GetByLabel('UI/LPStore/Accept'), func=self.Buy, padding=(5, 5, 5, 5)) 113 uicore.registry.SetFocus(self.amountEdit) 114 115 def Buy(self, *_args): 116 accepted = self.lpSvc.AcceptOffer(self.node, self.amountEdit.GetValue()) 117 if accepted == uiconst.ID_YES and self.utilMenu: 118 self.utilMenu.Close() 119 120 def Startup(self, *etc): 121 pass 122 123 def Load(self, data): 124 uthread.pool('lpStore::LPOfferEntry.Load_Thread', self.Load_Thread, data) 125 126 def Load_Thread(self, data): 127 abstractInfo = None 128 isCopy = False 129 if evetypes.GetCategoryID(data.typeID) == appConst.categoryBlueprint: 130 bpData = sm.GetService('blueprintSvc').GetBlueprintTypeCopy(typeID=data.typeID, runsRemaining=data.qty, original=False) 131 abstractInfo = utillib.KeyVal(bpData=bpData) 132 isCopy = True 133 self.sr.rewardInfoIcon.OnClick = (sm.GetService('info').ShowInfo, 134 data.typeID, 135 None, 136 abstractInfo) 137 self.LoadIcon(data.typeID, isCopy) 138 self.sr.rewardLabel.SetText(GetItemText(data.typeID, data.Get('qty', 1))) 139 self._LoadRequirementColumns(data) 140 self.CheckCanAcceptOffer(data) 141 self.CreateTooltipPanel() 142 143 def CreateTooltipPanel(self): 144 self.LoadTooltipPanel = self.LoadRewardTooltipPanel 145 146 def LoadIcon(self, typeID, isCopy): 147 self.sr.icon.LoadIconByTypeID(typeID=typeID, size=64, ignoreSize=True, isCopy=isCopy) 148 149 def CheckCanAcceptOffer(self, data): 150 if self.lpSvc.CanAcceptOffer(data): 151 self.sr.buyBtn.state = uiconst.UI_NORMAL 152 else: 153 self.sr.buyBtn.state = uiconst.UI_HIDDEN 154 self.sr.icon.spriteEffect = trinity.TR2_SFX_SOFTLIGHT 155 self.sr.icon.SetRGBA(1, 0, 0, 1) 156 self.sr.icon.saturation = 0.1 157 158 def _GetRewardCostHint(self): 159 requirements = {} 160 for requirementColumn in self.lpOfferRequirementColumns: 161 costLabelPath = requirementColumn.costLabelPath 162 if costLabelPath: 163 costName = requirementColumn.name 164 costNameText = localization.GetByLabel(costLabelPath) 165 costLabel = getLabelName(requirementColumn) 166 costLabelText = self.sr[costLabel].text 167 requirements[costName] = costNameText 168 requirements[costLabel] = costLabelText 169 170 return localization.GetByLabel('UI/LPStore/HintRewardCost', rewardLabel=self.sr.rewardLabel.text, **requirements) 171 172 def GetValidSlotForType(self, typeID): 173 return self.godma.GetPowerEffectForType(typeID) 174 175 def _GetTooltipItemTypeSortPriority(self, typeID): 176 categoryID = evetypes.GetCategoryID(typeID) 177 if categoryID == invconst.categoryShip: 178 priority = 1 179 elif categoryID == invconst.categoryShipSkin: 180 priority = 2 181 elif categoryID == invconst.categoryModule: 182 slotType = self.GetValidSlotForType(typeID) 183 if slotType == dogmaconst.effectHiPower: 184 priority = 3 185 elif slotType == dogmaconst.effectMedPower: 186 priority = 4 187 elif slotType == dogmaconst.effectLoPower: 188 priority = 5 189 else: 190 priority = 6 191 elif categoryID == invconst.categoryDrone: 192 priority = 7 193 elif categoryID == invconst.categoryCharge: 194 priority = 8 195 else: 196 priority = 9 197 return priority 198 199 def _CompareTooltipEntries(self, itemAndQuantity, otherItemAndQuantity): 200 itemTypeID, _ = itemAndQuantity 201 priority = self._GetTooltipItemTypeSortPriority(itemTypeID) 202 otherItemTypeID, _ = otherItemAndQuantity 203 otherPriority = self._GetTooltipItemTypeSortPriority(otherItemTypeID) 204 return priority - otherPriority 205 206 def LoadRewardTooltipPanel(self, tooltipPanel, *_args): 207 tooltipPanel.LoadGeneric3ColumnTemplate() 208 tooltipPanel.state = uiconst.UI_NORMAL 209 tooltipPanel.cellSpacing = 2 210 icon = eveIcon.Icon(parent=tooltipPanel, size=32, ignoreSize=True, align=uiconst.CENTER, state=uiconst.UI_DISABLED) 211 icon.LoadIconByTypeID(typeID=self.typeID, isCopy=True) 212 tooltipPanel.AddLabelMedium(text=GetItemText(self.typeID, self.qty), align=uiconst.CENTERLEFT) 213 tooltipPanel.AddInfoIcon(self.typeID, align=uiconst.CENTERRIGHT) 214 items = [] 215 isReqItems = False 216 if len(self.reqItems): 217 isReqItems = True 218 tooltipPanel.AddDivider() 219 tooltipPanel.AddLabelSmall(text=localization.GetByLabel('UI/LPStore/RequiredItems'), colSpan=3) 220 items = self.reqItems 221 elif len(self.lootItems): 222 tooltipPanel.AddDivider() 223 tooltipPanel.AddLabelSmall(text=localization.GetByLabel('UI/Inventory/Filters/CritContains'), colSpan=3) 224 items = self.lootItems 225 items = sorted(items, cmp=self._CompareTooltipEntries) 226 for typeID, qty in items: 227 eveIcon.Icon(parent=tooltipPanel, size=24, ignoreSize=True, align=uiconst.CENTER, state=uiconst.UI_DISABLED, typeID=typeID) 228 if not isReqItems: 229 qty = evetypes.GetPortionSize(typeID) * qty 230 itemLabel = tooltipPanel.AddLabelMedium(text=GetItemText(typeID, qty, checkIsBlueprint=False), align=uiconst.CENTERLEFT) 231 tooltipPanel.AddInfoIcon(typeID, align=uiconst.CENTERRIGHT) 232 if isReqItems and not self.lpSvc.HaveItem(typeID, qty): 233 itemLabel.color = Color.RED 234 235 def _LoadRequirementColumns(self, data): 236 for requirementColumn in self.lpOfferRequirementColumns: 237 self._LoadRequirementColumn(data, requirementColumn) 238 239 def _LoadRequirementColumn(self, data, requirementColumn): 240 requirementName = requirementColumn.name 241 cost = data.Get(requirementName, 0) 242 labelName = getLabelName(requirementColumn) 243 amountName = requirementColumn.amountName 244 amount = requirementColumn.formatAmount(cost) 245 amountHintPath = requirementColumn.amountHintPath 246 amountText = amount 247 if amountHintPath: 248 keywords = {amountName: amount} 249 amountText = localization.GetByLabel(amountHintPath, **keywords) 250 self.sr[labelName].SetText(amountText) 251 if not requirementColumn.checkAmount(cost): 252 self.sr[labelName].color = Color.RED 253 254 def OnColumnResize(self, newCols): 255 for container, width in zip(self.children[:], newCols): 256 container.width = width 257 258 self.sr.rewardLabel.width = self.sr.rewardParent.width - self.sr.rewardIconParent.width - self.sr.rewardLabel.left - self.labelMargin 259 260 def GetHeight(self, node, _width): 261 node.height = LPOfferEntry.entryHeight 262 return node.height 263 264 265 on_cosmetic_license_purchase_failed = Signal('on_cosmetic_license_purchase_failed') 266 267 class CosmeticLogoLPOfferEntry(LPOfferEntry): 268 269 def ApplyAttributes(self, attributes): 270 super(CosmeticLogoLPOfferEntry, self).ApplyAttributes(attributes) 271 self._showHilite = not self.node.isOwned 272 on_ship_cosmetics_license_change.connect(self.OnLicenseStatusChanged) 273 274 def _UpdateStatus(self): 275 self._showHilite = not self.node.isOwned 276 for requirement in self.lpOfferRequirementColumns: 277 labelName = getLabelName(requirement) 278 self.sr[labelName].opacity = 0.7 if self.node.isOwned else 1.0 279 self.sr[labelName].color = self.GetRowContentTint() 280 281 if self.sr.rewardlabel: 282 self.sr.rewardLabel.opacity = 0.7 if self.node.isOwned else 1.0 283 self.sr.rewardLabel.color = self.GetRowContentTint() 284 self.offerCont.Flush() 285 self.AddBuyButton() 286 if self.sr and self.sr.icon: 287 self.sr.icon.color = self.GetRowContentTint() 288 if self.node: 289 self.sr.icon.opacity = 0.7 if self.node.isOwned else 1.0 290 291 def AddRewardLabel(self): 292 rewardLabelContainer = Container(name='rewardLabelContainer', parent=self.sr.rewardParent, align=uiconst.TOALL) 293 self.sr.rewardLabel = LPStoreEntryLabel(parent=rewardLabelContainer, align=uiconst.CENTERLEFT, padTop=4, maxLines=3, color=self.GetRowContentTint(), opacity=0.7 if self.node.isOwned else 1.0) 294 295 def AddBuyButton(self): 296 self.offerCont = Container(name='buyButtonParent', parent=self, align=uiconst.TOLEFT, clipChildren=True) 297 if self.node.isOwned: 298 rewardAquiredCont = Container(name='rewardAquiredCont', parent=self.offerCont, align=uiconst.TOLEFT, padRight=20) 299 labelCont = Container(name='labelCont', parent=rewardAquiredCont, align=uiconst.TOLEFT) 300 rewardAquiredLabel = LPStoreEntryLabel(name='rewardAquiredLabel', parent=labelCont, align=uiconst.CENTER, text=GetByLabel('UI/ShipCosmetics/RewardAcquired'), color=self.GetRowContentTint(), opacity=0.9 if self.node.isOwned else 1.0) 301 labelWidth, labelHeight = rewardAquiredLabel.GetSize() 302 labelCont.SetSize(labelWidth, labelHeight) 303 tickCont = Container(name='tickCont', parent=rewardAquiredCont, align=uiconst.TORIGHT) 304 rewardAquiredTick = Sprite(name='rewardAquiredTick', parent=tickCont, align=uiconst.CENTER, texturePath='res:/UI/Texture/classes/SkillPlan/completedIcon.png', width=34, height=34) 305 tickWidth, tickHeight = rewardAquiredTick.GetSize() 306 tickCont.SetSize(tickWidth, tickHeight) 307 rewardAquiredWidth = labelWidth + tickWidth 308 rewardAquiredHeight = labelHeight + tickHeight 309 rewardAquiredCont.SetSize(rewardAquiredWidth, rewardAquiredHeight) 310 else: 311 self.sr.buyBtn = Button(name='buyBtn', parent=self.offerCont, label=localization.GetByLabel('UI/VirtualGoodsStore/Buttons/Buy'), align=uiconst.CENTERLEFT, padLeft=8, func=self.OnBuyBtn) 312 313 def GetRowContentTint(self): 314 if self.node.isOwned: 315 return Color.HextoRGBA('#8DC169') 316 return (1.0, 1.0, 1.0, 1.0) 317 318 def CreateTooltipPanel(self): 319 pass 320 321 def CreateIcon(self): 322 self.sr.icon = None 323 324 def LoadIcon(self, typeID, isCopy): 325 self.sr.icon = Sprite(name='logoIcon', parent=self.sr.rewardIconParent, align=uiconst.CENTER, state=uiconst.UI_DISABLED, texturePath=self.GetIconTexturePath(), color=self.GetRowContentTint(), opacity=0.7 if self.node.isOwned else 1.0) 326 self.sr.icon.width = self.iconSize 327 self.sr.icon.height = self.iconSize 328 329 def CheckCanAcceptOffer(self, data): 330 if self.sr.buyBtn: 331 if self.node.isOwned: 332 self.sr.buyBtn.state = uiconst.UI_HIDDEN 333 self.sr.buyBtn.disable(animate=False) 334 elif self.lpSvc.CanAcceptOffer(data): 335 self.sr.buyBtn.state = uiconst.UI_NORMAL 336 self.sr.buyBtn.enable(animate=False) 337 else: 338 self.sr.buyBtn.state = uiconst.UI_DISABLED 339 self.sr.buyBtn.disable(animate=False) 340 self.sr.icon.color = self.GetRowContentTint() 341 self.sr.icon.opacity = 0.7 if self.node.isOwned else 1.0 342 343 def GetIconTexturePath(self): 344 return None 345 346 def OnBuyBtn(self, *_args): 347 ok = uiconst.ID_NO 348 try: 349 ok = self.lpSvc.AcceptOffer(self.node, 1) 350 except RuntimeError as ex: 351 logger.exception('Could not complete LP Store purchase: %s' % ex) 352 on_cosmetic_license_purchase_failed() 353 354 if ok == uiconst.ID_NO: 355 on_cosmetic_license_purchase_failed() 356 357 def OnLicenseStatusChanged(self, licenseID, enable): 358 licenseData = sm.GetService('cosmeticsLicenseSvc').get_by_ship_license_type_id(self.node.typeID) 359 if licenseData and licenseData.licenseID == licenseID: 360 self.node.isOwned = enable 361 self._UpdateStatus() 362 363 def OnColumnResize(self, newCols): 364 super(CosmeticLogoLPOfferEntry, self).OnColumnResize(newCols) 365 366 367 class AllianceLogoLPOfferEntry(CosmeticLogoLPOfferEntry): 368 369 def ApplyAttributes(self, attributes): 370 super(AllianceLogoLPOfferEntry, self).ApplyAttributes(attributes) 371 372 def GetIconTexturePath(self): 373 return BACKGROUND_PATH_BY_TYPE.get(CosmeticsType.ALLIANCE_LOGO, '') 374 375 376 class CorporationLogoLPOfferEntry(CosmeticLogoLPOfferEntry): 377 378 def ApplyAttributes(self, attributes): 379 super(CorporationLogoLPOfferEntry, self).ApplyAttributes(attributes) 380 381 def GetIconTexturePath(self): 382 return BACKGROUND_PATH_BY_TYPE.get(CosmeticsType.CORPORATION_LOGO, '')