NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

playerOwned.py (22391B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\parklife\playerOwned.py
      2 import sys
      3 import blue
      4 import carbonui.const as uiconst
      5 import dogma.data
      6 import eve.common.script.mgt.posConst as pos
      7 import evetypes
      8 import localization
      9 import log
     10 import telemetry
     11 import uthread
     12 from carbon.common.script.sys.service import Service
     13 from eve.client.script.ui.util import uix
     14 from eve.client.script.ui.util import utilWindows
     15 from eve.common.lib import appConst as const
     16 from eve.common.script.net import eveMoniker
     17 from eveexceptions import UserError
     18 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     19 ONLINE_STATES = (pos.STRUCTURE_ONLINING,
     20  pos.STRUCTURE_REINFORCED,
     21  pos.STRUCTURE_ONLINE,
     22  pos.STRUCTURE_OPERATING,
     23  pos.STRUCTURE_VULNERABLE,
     24  pos.STRUCTURE_SHIELD_REINFORCE,
     25  pos.STRUCTURE_ARMOR_REINFORCE,
     26  pos.STRUCTURE_INVULNERABLE)
     27 UNANCHORABLE_STATES = (pos.STRUCTURE_ONLINING,
     28  pos.STRUCTURE_REINFORCED,
     29  pos.STRUCTURE_ONLINE,
     30  pos.STRUCTURE_OPERATING,
     31  pos.STRUCTURE_UNANCHORED,
     32  pos.STRUCTURE_VULNERABLE,
     33  pos.STRUCTURE_SHIELD_REINFORCE,
     34  pos.STRUCTURE_ARMOR_REINFORCE,
     35  pos.STRUCTURE_INVULNERABLE)
     36 
     37 class PlayerOwned(Service):
     38     __guid__ = 'svc.pwn'
     39     __exportedcalls__ = {'CanAnchorStructure': [],
     40      'CanUnanchorStructure': [],
     41      'CanOnlineStructure': [],
     42      'CanOfflineStructure': [],
     43      'CanAssumeControlStructure': [],
     44      'GetStructureState': [],
     45      'CompareShipStructureHarmonic': [],
     46      'CheckAnchoringPosition': [],
     47      'Anchor': [],
     48      'EnterTowerPassword': [],
     49      'EnterShipPassword': [],
     50      'AssumeStructureControl': [],
     51      'RelinquishStructureControl': [],
     52      'UnlockStructureTarget': [],
     53      'GetCurrentTarget': [],
     54      'ClrCurrentTarget': [],
     55      'GetCurrentControl': []}
     56     __notifyevents__ = ['OnSlimItemChange',
     57      'OnTargetOBO',
     58      'DoSessionChanging',
     59      'DoBallsAdded',
     60      'DoBallRemove',
     61      'DoBallsRemove']
     62     __dependencies__ = ['godma', 'michelle']
     63 
     64     def Run(self, memStream = None):
     65         Service.Run(self, memStream)
     66         sm.FavourMe(self.DoBallsAdded)
     67         self.currenttargets = {}
     68         self.currentcontrol = {}
     69         self.currentlyAssuming = {}
     70 
     71     def Stop(self, stream):
     72         Service.Stop(self)
     73 
     74     def OnSlimItemChange(self, oldItem, newItem):
     75         if newItem.categoryID != const.categoryStarbase:
     76             return
     77         if newItem.posState == oldItem.posState and newItem.posTimestamp == oldItem.posTimestamp and newItem.controllerID == oldItem.controllerID and newItem.incapacitated == oldItem.incapacitated:
     78             return
     79         if oldItem.controllerID is not None and newItem.controllerID == None:
     80             uthread.new(self.RelinquishStructureControl, oldItem, silent=True, force=True)
     81         stateName, stateTimestamp, stateDelay = self.GetStructureState(newItem)
     82         if stateName == 'onlining':
     83             uthread.pool('pwn::StalledOnlineEvent', self.StalledOnlineEvent, newItem.itemID, newItem.posState, stateTimestamp, stateDelay)
     84 
     85     def StalledOnlineEvent(self, itemID, posState, stateTimestamp, stateDelay):
     86         item = self.michelle.GetItem(itemID)
     87         if item is None or item.posState != posState or item.posTimestamp != stateTimestamp:
     88             return
     89         x1, x2, stateDelay = self.GetStructureState(item)
     90         blue.pyos.synchro.SleepWallclock(stateDelay)
     91         item = self.michelle.GetItem(itemID)
     92         if item is None:
     93             return
     94         if item.posState != posState or item.posTimestamp != stateTimestamp:
     95             if item.posState != pos.STRUCTURE_ONLINE:
     96                 return
     97         sm.ScatterEvent('OnStructureFullyOnline', itemID)
     98         if item.controlTowerID is not None:
     99             sm.ScatterEvent('OnSpecialFX', item.controlTowerID, itemID, item.typeID, None, None, 'effects.StructureOnlined', 0, 1, 0)
    100 
    101     def CompareShipStructureHarmonic(self, shipID, itemID):
    102         item = self.michelle.GetItem(itemID)
    103         if not item:
    104             return False
    105         if item.groupID == const.groupControlTower:
    106             controlTowerID = itemID
    107             towerItem = item
    108         else:
    109             controlTowerID = item.controlTowerID
    110             if controlTowerID is None:
    111                 return False
    112             towerItem = self.michelle.GetItem(controlTowerID)
    113             if towerItem is None:
    114                 return False
    115         forceFieldID = towerItem.forceFieldID
    116         if forceFieldID is None:
    117             return False
    118         fieldBall = self.michelle.GetBall(forceFieldID)
    119         shipBall = self.michelle.GetBall(shipID)
    120         if not shipBall or not fieldBall:
    121             return False
    122         if fieldBall.harmonic != -1 and fieldBall.harmonic == shipBall.harmonic:
    123             return True
    124         return False
    125 
    126     def GetStructureState(self, slimItem):
    127         stateName = 'Unknown_State_%s' % slimItem.posState
    128         stateTimestamp = None
    129         stateDelay = None
    130         godmaSM = self.godma.GetStateManager()
    131         if slimItem.posState == pos.STRUCTURE_ANCHORED:
    132             stateName = const.pwnStructureStateAnchored
    133             if slimItem.posTimestamp is not None:
    134                 delayMs = godmaSM.GetType(slimItem.typeID).anchoringDelay
    135                 if blue.os.GetWallclockTime() - slimItem.posTimestamp < delayMs * 10000:
    136                     stateName = const.pwnStructureStateAnchoring
    137                     stateTimestamp = slimItem.posTimestamp
    138                     stateDelay = delayMs
    139         elif slimItem.posState == pos.STRUCTURE_ONLINING:
    140             stateName = const.pwnStructureStateOnline
    141             if slimItem.posState == pos.STRUCTURE_ONLINING and slimItem.posTimestamp is not None:
    142                 delayMs = godmaSM.GetType(slimItem.typeID).onliningDelay
    143                 if blue.os.GetWallclockTime() - slimItem.posTimestamp < delayMs * 10000:
    144                     stateName = const.pwnStructureStateOnlining
    145                     stateTimestamp = slimItem.posTimestamp
    146                     stateDelay = delayMs
    147         elif slimItem.posState == pos.STRUCTURE_UNANCHORED:
    148             stateName = const.pwnStructureStateUnanchored
    149             if slimItem.posTimestamp is not None:
    150                 delayMs = godmaSM.GetType(slimItem.typeID).unanchoringDelay
    151                 if blue.os.GetWallclockTime() - slimItem.posTimestamp < delayMs * 10000:
    152                     stateName = const.pwnStructureStateUnanchoring
    153                     stateTimestamp = slimItem.posTimestamp
    154                     stateDelay = delayMs
    155         elif slimItem.posState == pos.STRUCTURE_VULNERABLE:
    156             stateName = const.pwnStructureStateVulnerable
    157         elif slimItem.posState == pos.STRUCTURE_INVULNERABLE:
    158             stateName = const.pwnStructureStateInvulnerable
    159         elif slimItem.posState == pos.STRUCTURE_REINFORCED:
    160             delayMs = (blue.os.GetWallclockTime() - slimItem.posTimestamp) / 10000
    161             if delayMs < 0:
    162                 stateName = const.pwnStructureStateReinforced
    163                 stateDelay = -delayMs
    164                 stateTimestamp = blue.os.GetWallclockTime() + delayMs
    165         elif slimItem.posState in (pos.STRUCTURE_SHIELD_REINFORCE, pos.STRUCTURE_ARMOR_REINFORCE):
    166             stateName = const.pwnStructureStateReinforced
    167             stateTimestamp = slimItem.posTimestamp + slimItem.posDelayTime
    168             stateDelay = slimItem.posDelayTime
    169         elif slimItem.posState == pos.STRUCTURE_OPERATING:
    170             stateName = const.pwnStructureStateOnline
    171             delayMs = (blue.os.GetWallclockTime() - slimItem.posTimestamp) / 10000
    172             if delayMs < 0:
    173                 stateName = const.pwnStructureStateOperating
    174                 stateDelay = -delayMs
    175                 stateTimestamp = blue.os.GetWallclockTime() + delayMs
    176         elif slimItem.posState == pos.STRUCTURE_ONLINE:
    177             stateName = const.pwnStructureStateOnline
    178         if slimItem.incapacitated:
    179             stateName = const.pwnStructureStateIncapacitated
    180         return (stateName, stateTimestamp, stateDelay)
    181 
    182     def EnterTowerPassword(self, towerID):
    183         password = utilWindows.NamePopup(caption=localization.GetByLabel('UI/Inflight/POS/TowerShieldHarmonic'), label=localization.GetByLabel('UI/Inflight/POS/EnterTheSharedSecret'), setvalue='', maxLength=50, passwordChar='*')
    184         if password is None:
    185             return
    186         posMgr = eveMoniker.GetPOSMgr()
    187         posMgr.SetTowerPassword(towerID, password)
    188 
    189     def EnterShipPassword(self):
    190         format = [{'type': 'text',
    191           'refreshheight': 1,
    192           'text': localization.GetByLabel('UI/Inflight/POS/EnterHarmonicPassword'),
    193           'frame': 0}, {'type': 'edit',
    194           'setvalue': '',
    195           'label': '_hide',
    196           'key': 'name',
    197           'maxLength': 50,
    198           'passwordChar': '*',
    199           'setfocus': 1,
    200           'frame': 0}]
    201         retval = uix.HybridWnd(format, caption=localization.GetByLabel('UI/Inflight/POS/ShipShieldHarmonic'), windowID='enterShipPassword', modal=1, buttons=uiconst.OKCANCEL, icon=uiconst.OKCANCEL, minW=360, minH=120, unresizeAble=True)
    202         if retval is not None:
    203             if session.stationid:
    204                 prompt_player_fsd_dialog('CannotSetShieldHarmonicPassword')
    205             else:
    206                 ship = eveMoniker.GetShipAccess()
    207                 ship.SetShipPassword(retval['name'])
    208 
    209     def Anchor(self, itemID, position):
    210         item = sm.GetService('michelle').GetItem(itemID)
    211         if item is None:
    212             return
    213         for row in dogma.data.get_type_effects(item.typeID):
    214             if row.effectID == const.effectAnchorDropForStructures:
    215                 posMgr = eveMoniker.GetPOSMgr()
    216                 posMgr.AnchorStructure(itemID, position)
    217                 break
    218 
    219     def CheckAnchoringPosition(self, itemID, position):
    220         item = self.michelle.GetItem(itemID)
    221         if item is None:
    222             return
    223         if item.categoryID != const.categoryStarbase:
    224             raise UserError('CantConfigureThat')
    225         bp = self.michelle.GetBallpark()
    226         shipBall = bp.GetBall(session.shipid)
    227         itemBall = bp.GetBall(itemID)
    228         if item.groupID == const.groupControlTower:
    229             actualDistance = bp.GetCenterDist(session.shipid, itemID) - shipBall.radius - itemBall.radius
    230             if actualDistance > 30000:
    231                 raise UserError('CantConfigureDistant2', {'actual': actualDistance,
    232                  'needed': 30000})
    233             self.CheckForStructures(itemID)
    234         else:
    235             towerID = self.LocateControlTower(itemID, 'CantAnchorRequireTower')
    236             self.CheckTowerAvailablility(towerID, itemID)
    237 
    238     def CheckForStructures(self, towerID):
    239         bp = self.michelle.GetBallpark()
    240         if bp is None:
    241             return
    242         towerItem = self.michelle.GetItem(towerID)
    243         if towerItem is None:
    244             return
    245         typeID = towerItem.typeID
    246         maxRange = self.godma.GetType(typeID).maxStructureDistance
    247         self.LogInfo('CheckForStructures', towerID, maxRange)
    248         for ballID in bp.balls.itervalues():
    249             if ballID < 0:
    250                 continue
    251             self.LogInfo('CheckForStructures.iteration', ballID)
    252             ballItem = self.michelle.GetItem(ballID)
    253             if ballItem is None:
    254                 continue
    255             if ballItem.categoryID == const.categoryStarbase:
    256                 ball = bp.GetBall(ballID)
    257                 if not ball.isFree:
    258                     raise UserError('CantAnchorTowerInvalidStructures', {'typeID': ballItem.typeID})
    259                 self.LogInfo('Anchor ignore', evetypes.GetName(ballItem.typeID))
    260 
    261     def LocateControlTower(self, locusID, raiseError = None):
    262         bp = self.michelle.GetBallpark()
    263         if bp is None:
    264             return
    265         for ballID in bp.GetBallIdsAndDistInRange(locusID, 300000):
    266             if ballID < 0:
    267                 continue
    268             item = self.michelle.GetItem(ballID)
    269             if item is None or item.groupID != const.groupControlTower:
    270                 continue
    271             maxDistance = self.godma.GetType(item.typeID).maxStructureDistance
    272             if bp.DistanceBetween(ballID, locusID) <= maxDistance:
    273                 return ballID
    274 
    275         if raiseError is not None:
    276             item = self.michelle.GetItem(locusID)
    277             raise UserError(raiseError, {'itemTypeID': item.typeID})
    278 
    279     def CheckTowerAvailablility(self, towerID, structureID):
    280         if towerID is None:
    281             return
    282         if towerID != structureID:
    283             if not self.IsStructureFullyOnline(towerID):
    284                 raise UserError('CantTowerNotOnline')
    285 
    286     def IsStructureFullyAnchored(self, itemID):
    287         slimItem = self.GetSlimItem(itemID)
    288         if slimItem is None:
    289             return 0
    290         if slimItem.posState != pos.STRUCTURE_ANCHORED:
    291             return 0
    292         if slimItem.posTimestamp is not None:
    293             godmaSM = self.godma.GetStateManager()
    294             delayMs = godmaSM.GetType(slimItem.typeID).anchoringDelay
    295             if blue.os.GetWallclockTime() - slimItem.posTimestamp < delayMs * 10000:
    296                 return 0
    297         return 1
    298 
    299     def IsStructureFullyOnline(self, itemID):
    300         slimItem = self.GetSlimItem(itemID)
    301         if slimItem is None:
    302             return 0
    303         if not hasattr(slimItem, 'posState'):
    304             return 0
    305         if slimItem.posState not in ONLINE_STATES:
    306             return 0
    307         if slimItem.posState == pos.STRUCTURE_ONLINING and slimItem.posTimestamp is not None:
    308             godmaSM = self.godma.GetStateManager()
    309             delayMs = godmaSM.GetType(slimItem.typeID).onliningDelay
    310             if blue.os.GetWallclockTime() - slimItem.posTimestamp < delayMs * 10000:
    311                 return 0
    312         return 1
    313 
    314     def IsStructureFullyUnanchored(self, itemID):
    315         slimItem = self.GetSlimItem(itemID)
    316         if slimItem is None:
    317             return 0
    318         if slimItem.posState != pos.STRUCTURE_UNANCHORED:
    319             return 0
    320         if slimItem.posTimestamp is not None:
    321             godmaSM = self.godma.GetStateManager()
    322             delayMs = godmaSM.GetType(slimItem.typeID).unanchoringDelay
    323             if blue.os.GetWallclockTime() - slimItem.posTimestamp < delayMs * 10000:
    324                 return 0
    325         return 1
    326 
    327     def CanAnchorStructure(self, itemID):
    328         return self.IsStructureFullyUnanchored(itemID)
    329 
    330     def CanOnlineStructure(self, itemID, fullyAnchored = None):
    331         return self.IsStructureFullyAnchored(itemID)
    332 
    333     def CanOfflineStructure(self, itemID, fullyOnline = None):
    334         return self.IsStructureFullyOnline(itemID)
    335 
    336     def CanUnanchorStructure(self, itemID):
    337         slimItem = self.GetSlimItem(itemID)
    338         if slimItem is None:
    339             return 0
    340         godmaSM = self.godma.GetStateManager()
    341         if slimItem.posState == pos.STRUCTURE_ANCHORED:
    342             if slimItem.posTimestamp is not None:
    343                 delayMs = godmaSM.GetType(slimItem.typeID).anchoringDelay
    344                 if blue.os.GetWallclockTime() - slimItem.posTimestamp < delayMs * 10000:
    345                     return 0
    346         elif slimItem.posState in UNANCHORABLE_STATES:
    347             return 0
    348         return godmaSM.TypeHasEffect(slimItem.typeID, const.effectAnchorLiftForStructures)
    349 
    350     def StructureIsOrphan(self, itemID):
    351         item = self.michelle.GetItem(itemID)
    352         if item is None:
    353             return False
    354         if item.categoryID == const.categorySovereigntyStructure:
    355             return False
    356         if item.groupID == const.groupControlTower:
    357             return False
    358         controlTowerID = item.controlTowerID
    359         if controlTowerID is None:
    360             return True
    361         towerItem = self.michelle.GetItem(controlTowerID)
    362         if towerItem is None:
    363             return True
    364         return False
    365 
    366     def DoBallsAdded(self, *args, **kw):
    367         import stackless
    368         import blue
    369         t = stackless.getcurrent()
    370         timer = t.PushTimer(blue.pyos.taskletTimer.GetCurrent() + '::playerOwned')
    371         try:
    372             return self.DoBallsAdded_(*args, **kw)
    373         finally:
    374             t.PopTimer(timer)
    375 
    376     def DoBallsAdded_(self, ballsToAdd):
    377         for ball, slimItem in ballsToAdd:
    378             try:
    379                 if slimItem is None:
    380                     continue
    381                 if slimItem.categoryID != const.categoryStarbase:
    382                     continue
    383                 controllerID = slimItem.controllerID
    384                 if controllerID is not None and controllerID == session.shipid:
    385                     uthread.new(self.RelinquishStructureControl, slimItem)
    386             except:
    387                 self.LogError('DoBallsAdded - failed to say i have control', (ball, slimItem))
    388                 log.LogTraceback()
    389                 sys.exc_clear()
    390 
    391     @telemetry.ZONE_METHOD
    392     def DoBallsRemove(self, pythonBalls, isRelease):
    393         for ball, slimItem, terminal in pythonBalls:
    394             self.DoBallRemove(ball, slimItem, terminal)
    395 
    396     def DoBallRemove(self, ball, slimItem, terminal):
    397         if slimItem is None:
    398             return
    399         if slimItem.categoryID != const.categoryStarbase:
    400             return
    401         if slimItem.controllerID == session.charid:
    402             uthread.new(self.RelinquishStructureControl, slimItem, silent=True, force=True)
    403 
    404     def DoSessionChanging(self, isRemote, session, change):
    405         if 'stationid' in change:
    406             self.currenttargets = {}
    407             self.currentcontrol = {}
    408 
    409     def CanAssumeControlStructure(self, structureID):
    410         item = sm.GetService('michelle').GetItem(structureID)
    411         if item is None:
    412             return 0
    413         for typeAttribute in dogma.data.get_type_attributes(item.typeID):
    414             if typeAttribute.attributeID == const.attributePosPlayerControlStructure:
    415                 return 1
    416 
    417         return 0
    418 
    419     def AssumeStructureControl(self, slimItem, silent = False, force = False):
    420         item = sm.GetService('michelle').GetItem(slimItem.itemID) or slimItem
    421         if item and getattr(item, 'itemID', None) and (item.itemID in self.currentlyAssuming or item.itemID in self.currentcontrol):
    422             raise UserError('StructureControlled', {'item': (const.UE_TYPEID, item.typeID)})
    423         if slimItem.posState < pos.STRUCTURE_ONLINING:
    424             raise UserError('StructureNotControllableUntilOnline', {'item': (const.UE_TYPEID, item.typeID)})
    425         self.currentlyAssuming[item.itemID] = True
    426         if item and not item.controllerID or force:
    427             for typeAttribute in dogma.data.get_type_attributes(item.typeID):
    428                 if typeAttribute.attributeID == const.attributePosPlayerControlStructure:
    429                     self.currentcontrol[item.itemID] = True
    430                     if not silent:
    431                         try:
    432                             posMgr = eveMoniker.GetPOSMgr()
    433                             posMgr.AssumeStructureControl(item.itemID)
    434                         except UserError as e:
    435                             del self.currentcontrol[item.itemID]
    436                             self.currentlyAssuming.pop(item.itemID, None)
    437                             prompt_player_fsd_dialog(e.msg, e.dict)
    438                             sys.exc_clear()
    439 
    440                     sm.ScatterEvent('OnAssumeStructureControl', item.itemID)
    441                     break
    442 
    443         self.currentlyAssuming.pop(item.itemID, None)
    444 
    445     def RelinquishStructureControl(self, slimItem, silent = False, force = False):
    446         item = sm.GetService('michelle').GetItem(slimItem.itemID) or slimItem
    447         if item and item.controllerID or force:
    448             for typeAttribute in dogma.data.get_type_attributes(item.typeID):
    449                 if typeAttribute.attributeID == const.attributePosPlayerControlStructure:
    450                     if item.itemID in self.currentcontrol:
    451                         del self.currentcontrol[item.itemID]
    452                     if item.itemID in self.currenttargets:
    453                         del self.currenttargets[item.itemID]
    454                     if not silent:
    455                         try:
    456                             posMgr = eveMoniker.GetPOSMgr()
    457                             posMgr.RelinquishStructureControl(item.itemID)
    458                         except UserError as e:
    459                             prompt_player_fsd_dialog(e.msg, e.dict)
    460                             sys.exc_clear()
    461 
    462                     sm.ScatterEvent('OnRelinquishStructureControl', item.itemID)
    463                     break
    464 
    465     def UnlockStructureTarget(self, structureID):
    466         if structureID in self.currenttargets:
    467             sm.GetService('pwntarget').UnLockTargetOBO(structureID, self.currenttargets[structureID])
    468             del self.currenttargets[structureID]
    469 
    470     def GetControllerIDName(self, itemID):
    471         slimItem = self.GetSlimItem(itemID)
    472         if slimItem is None:
    473             return (0, '')
    474         controller = getattr(slimItem, 'controllerID', 0)
    475         if controller:
    476             ct = cfg.eveowners.Get(controller).name
    477         else:
    478             ct = localization.GetByLabel('UI/Generic/NotAvailableShort')
    479             if itemID in self.currenttargets:
    480                 del self.currenttargets[itemID]
    481         return (controller, ct)
    482 
    483     def GetDogmaLM(self):
    484         return self.godma.GetStateManager().GetDogmaLM()
    485 
    486     def OnTargetOBO(self, what, sid = None, tid = None, reason = None):
    487         if what == 'add':
    488             self.currenttargets[sid] = tid
    489         elif what == 'lost':
    490             if sid in self.currenttargets:
    491                 del self.currenttargets[sid]
    492 
    493     def ClrCurrentTarget(self, structureID = None):
    494         if structureID and structureID in self.currenttargets:
    495             del self.currenttargets[structureID]
    496             del self.currentcontrol[structureID]
    497         elif structureID is None:
    498             self.currenttargets = {}
    499             self.currentcontrol = {}
    500 
    501     def GetCurrentTarget(self, structureID = None):
    502         if structureID is None:
    503             return self.currenttargets
    504         return self.currenttargets.get(structureID, None)
    505 
    506     def GetCurrentControl(self, structureID = None):
    507         if structureID is None:
    508             return self.currentcontrol
    509         return self.currentcontrol.get(structureID, None)
    510 
    511     def GetSlimItem(self, itemID):
    512         bp = sm.GetService('michelle').GetBallpark()
    513         if bp is None:
    514             return
    515         slimItem = bp.GetInvItem(itemID)
    516         return slimItem