Ejemplo n.º 1
0
    def __init__(self, owner, consumables, equipment, crewSkills):
        AvatarControllerBase.__init__(self, owner)
        self.__skillConditions = SkillConditions(owner, SKILL_EVENT)
        self.__objects = {
            OBJ_GROUPS.CREW: [
                CrewSkills(owner, obj, self.__skillConditions, index)
                for index, obj in enumerate(crewSkills)
            ],
            OBJ_GROUPS.CONSUMABLES:
            [ConsumableEquipmentFeaturedObject(obj) for obj in consumables],
            OBJ_GROUPS.EQUIPMENT: [
                EquipmentFeaturedObject(obj, getCrewSkillsID(crewSkills))
                for obj in equipment
            ],
            OBJ_GROUPS.CAMOUFLAGE: [
                CamouflageFeatureObject(owner.camouflageBonusSchemeName,
                                        owner.isCamouflageSpecializedForCurMap)
            ]
        }
        self.__specializationIdToObj = {}
        for crewMember in self.__objects[OBJ_GROUPS.CREW]:
            self.__specializationIdToObj[
                crewMember.specializationID] = crewMember

        self.eModifiersChanged = Event.Event()
        self.modifiers = Modifiers()
        readyToUseSubscriptions = (
            EventSubscription(c.eReadyToUse, self._onConsumableReadyToUse)
            for c in self.__objects[OBJ_GROUPS.CONSUMABLES])
        self._subscription = CompositeSubscription(*readyToUseSubscriptions)
        if IS_CELLAPP:
            self._subscription.extend(
                EventSubscription(self._owner.eDestruction, self.onOwnerDeath))
        self._subscription.subscribe()
Ejemplo n.º 2
0
 def _update(self, gameResult, winState):
     playerTeamIndex = self._player.teamIndex
     enemyTeamIndex = 1 - self._player.teamIndex
     logger.debug('RESULT::::: {0}'.format(gameResult))
     if gameResult in GAME_RESULT_LOC_IDS:
         resIndex = 2 if winState == 2 else int(playerTeamIndex != winState)
         reason = GAME_RESULT_LOC_IDS[gameResult][resIndex]
         self._model.reason = reason
         logger.debug('Update: {0}, {1}, {2}, {3}'.format(
             gameResult, winState, playerTeamIndex, reason))
     self._model.winnerTeamIndex = winState
     self._updateBattleTime()
     scoreGlobal = self._clientArena.gameMode.scoreGlobal
     self._model.allyPoints = scoreGlobal[playerTeamIndex]
     self._model.enemyPoints = scoreGlobal[enemyTeamIndex]
     self._updatePlayerTeamRate()
     self._updatePlayerEconomics()
     if not self._updateRateSubscription:
         self._updateRateSubscription = CompositeSubscription(
             EventSubscription(self._clientArena.onEconomicEvents,
                               self._updatePlayerTeamRate),
             EventSubscription(self._clientArena.onEconomicPlayersPoints,
                               self._updatePlayerTeamRate))
         self._updateRateSubscription.subscribe()
     self._updateBestRankData()
Ejemplo n.º 3
0
 def __init__(self, clientArena):
     super(ACGameModeClient, self).__init__(clientArena)
     self._scoreGlobal = (0, 0)
     self._globalCounters = {}
     self._sectors = {}
     self._currentTick = 0
     self._currentTickStartedAt = self.player.arenaStartTime
     self._globalTime = 0
     self._dynamicTime = 0
     self._isReady = False
     self._eManager = EventManager()
     self.eGameModeReady = Event(self._eManager)
     self._rocketV2Manager = RocketV2Manager.RocketV2Manager(self)
     self._signalFlaresManager = SignalFlaresManager.SignalFlaresManager(
         self)
     self._waveInfoManager = WaveInfoManager(self)
     self._lastPlayerManager = LastPlayerManager(self)
     self._pendingEvents = []
     self.createSectorsData()
     self.registerArenaUpdateEvents(self.updateEventsMap)
     gameActionsManager = self.clientArena.gameActionsManager
     self._subscription = CompositeSubscription(
         EventSubscription(gameActionsManager.eWaveAdded,
                           self._onASWaveAdded),
         EventSubscription(gameActionsManager.eWaveRemoved,
                           self._onASWaveRemoved),
         EventSubscription(gameActionsManager.eWaveStateChanged,
                           self._onASWaveStateChanged),
         EventSubscription(gameActionsManager.eBomberStateChanged,
                           self._onASBomberStateChanged))
     self._subscription.subscribe()
 def __init__(self, features):
     self._logger = BWLogging.getLogger(self.__class__.__name__)
     self._model = features.require(
         Feature.GAME_MODEL).domination.sectorsGameEffects
     self._clientArena = features.require(Feature.CLIENT_ARENA)
     self._db = features.require(Feature.DB_LOGIC)
     self._playerAvatar = features.require(Feature.PLAYER_AVATAR)
     self._gameMode = self._clientArena.gameMode
     self._disableBomberCallbacks = {}
     self._subscription = CompositeSubscription(
         EDSubscription(self.gameMode, AC_EVENTS.BOMBERS_LAUNCHED,
                        self._onBombersLaunched),
         EDSubscription(self.gameMode, AC_EVENTS.BOMBER_ATTACK_NOTIFIED,
                        self._onBomberAttackNotified),
         EDSubscription(self.gameMode, AC_EVENTS.BOMBER_BOMBS_DROPPED,
                        self._onBomberBombsDropped),
         EDSubscription(self.gameMode, AC_EVENTS.BOMBERS_DIED,
                        self._onBombersDied),
         EDSubscription(self.gameMode, AC_EVENTS.BOMBER_IN_WAVE_DIED,
                        self._onBomberInWaveDied),
         EDSubscription(self.gameMode.rocketV2Manager,
                        AC_EVENTS.ROCKET_V2_EFFECT_STARTED,
                        self._onRocketEffectStarted),
         EDSubscription(self.gameMode.rocketV2Manager,
                        AC_EVENTS.ROCKET_V2_EFFECT_ENDED,
                        self._onRocketEffectEnded),
         EventSubscription(self._clientArena.onReceiveMarkerMessage,
                           self._onReceiveMarkerMessage))
     self.gameMode.addEventHandler(
         AC_EVENTS.ROCKET_V2_TARGET_SECTOR_CHANGED,
         self._onRocketEffectSectorChanged)
     if self.gameMode.isReady:
         self._setupModel()
     else:
         self.gameMode.eGameModeReady += self._setupModel
Ejemplo n.º 5
0
 def _subscribe(self):
     self._subscription = CompositeSubscription(
         EventSubscription(self._clientArena.onAvatarPlaneTypeRankChanged,
                           self._updateAvatarPlaneTypeRank),
         EventSubscription(self._clientArena.onAvatarPlaneTypeRankChanged,
                           self._updatePlaneScoresData),
         EventSubscription(
             self._clientArena.onPlayerEconomicExtDataReceived,
             self._updatePlaneScoresData),
         EventSubscription(self._clientArena.onAvatarChangedPlane,
                           self._updateAvatarPlaneTypeRank),
         EventSubscription(self._clientArena.onAvatarEnterWorld,
                           self._onAvatarEnterWorld),
         EventSubscription(self._clientArena.onAvatarLeaveWorld,
                           self._onAvatarLeaveWorld),
         EventSubscription(self._clientArena.onEconomicPlayersPoints,
                           self._onPlayersPoints),
         EventSubscription(self._clientArena.onUpdatePlayerStats,
                           self._onUpdatePlayerStats))
     self._subscription.subscribe()
     if self._clientArena.isAllServerDataReceived():
         self._onNewAvatarsInfo(None)
     else:
         self._clientArena.onNewAvatarsInfo += self._onNewAvatarsInfo
     return
Ejemplo n.º 6
0
class BattleLogSource(DataSource):
    """
    @type _model: gui.HUD2.features.battleEvent.BattleLogModel.BattleLogModel
    @type _economics: clientEconomics.ClientEconomic.ClientEconomic
    @type _player: PlayerAvatar.PlayerAvatar
    """
    def __init__(self, features):
        self._model = features.require(Feature.GAME_MODEL).battlePoints
        self._economics = features.require(Feature.CLIENT_ECONOMICS)
        self._player = features.require(Feature.PLAYER_AVATAR)
        self._clientArena = features.require(Feature.CLIENT_ARENA)
        self._subscription = CompositeSubscription(
            EventSubscription(self._player.eAchievementUnlocked,
                              self._onAchievementUnlocked),
            EventSubscription(self._player.eQuestCompleted,
                              self._onQuestCompleted),
            EventSubscription(self._clientArena.onAvatarPlaneTypeRankChanged,
                              self._onPlayerPlaneTypeRankUpdated))
        self._subscription.subscribe()
        self._economics.assignModelView(self)

    def dispose(self):
        self._subscription.unsubscribe()
        self._subscription = None
        self._economics.assignModelView(None)
        self._economics = None
        self._model = None
        self._player = None
        return

    def refresh(self, totalPoints, totalExp, newEvents):
        """
        @param totalPoints: int
        @param newEvents: list()
        look ClientEconomics.onEconomicEvents() for parameters of each event
        """
        from debug_utils import LOG_DEBUG
        LOG_DEBUG(
            'ECOVIEW: BattleLogSource: new events {0}, bp {1}, mp {2}'.format(
                len(newEvents), totalPoints, totalExp))
        for event in newEvents:
            self._model.battleEvent = event

        self._model.totalPoints = totalPoints
        self._model.totalExp = totalExp

    def _onQuestCompleted(self, questID):
        e = createQuestCompletedEventModel(questID)
        self._model.battleEvent = e

    def _onAchievementUnlocked(self, achievementID):
        e = createAchievementUnlockedEventModel(achievementID)
        self._model.battleEvent = e

    def _onPlayerPlaneTypeRankUpdated(self, avatarID, planeType, oldRankID,
                                      rankID, *args, **kwargs):
        if avatarID == self._player.id and planeType == self._player.planeType:
            e = createRankGainedEventModel(rankID)
            self._model.battleEvent = e
 def _subscribe(self):
     self._subscription = CompositeSubscription(
         EventSubscription(self._gameEnvironment.eAvatarHealthChange,
                           self._onAvatarHealthChanged),
         EDSubscription(self._gameMode, AC_EVENTS.BOMBERS_LAUNCHED,
                        self._onACBombersWaveLaunched),
         EDSubscription(self._gameMode, AC_EVENTS.BOMBERS_DIED,
                        self._onACBombersWaveDied),
         EDSubscription(self._gameMode, AC_EVENTS.BOMBERS_ATTACK_STARTED,
                        self._onACBombersAttackStarted))
     self._subscription.subscribe()
Ejemplo n.º 8
0
 def __subscribe(self):
     self._subscription = CompositeSubscription(
         EventSubscription(self._playerAvatar.eUpdateHealth,
                           self._onUpdateHealth),
         EventSubscription(self._playerAvatar.onStateChanged,
                           self._onStateChanged),
         EventSubscription(self._playerAvatar.eTacticalRespawnEnd,
                           self._fillPlaneData),
         EventSubscription(self._gameEnv.ePlayerGunnerChangedTurret,
                           self._updateModelShootingDistance))
     self._subscription.subscribe()
Ejemplo n.º 9
0
 def __init__(self, features):
     self._model = features.require(Feature.GAME_MODEL).battlePoints
     self._economics = features.require(Feature.CLIENT_ECONOMICS)
     self._player = features.require(Feature.PLAYER_AVATAR)
     self._clientArena = features.require(Feature.CLIENT_ARENA)
     self._subscription = CompositeSubscription(
         EventSubscription(self._player.eAchievementUnlocked,
                           self._onAchievementUnlocked),
         EventSubscription(self._player.eQuestCompleted,
                           self._onQuestCompleted),
         EventSubscription(self._clientArena.onAvatarPlaneTypeRankChanged,
                           self._onPlayerPlaneTypeRankUpdated))
     self._subscription.subscribe()
     self._economics.assignModelView(self)
Ejemplo n.º 10
0
class GameActionsManagerProxy(object):

    def __init__(self):
        self._entity = None
        self._subscription = None
        self._eManager = EventManager()
        self.eWaveAdded = Event(self._eManager)
        self.eWaveRemoved = Event(self._eManager)
        self.eWaveStateChanged = Event(self._eManager)
        self.eBomberStateChanged = Event(self._eManager)
        return

    @property
    def activeASWaves(self):
        if self._entity:
            return self._entity.activeASWaves
        return []

    def onManagerEnterWorld(self, entity):
        raise not self._entity or AssertionError('Attempt to override registered manager, old = {0}, new = {1}'.format(self._entity, entity))
        self._entity = entity
        self._subscribeOn(entity)

    def onManagerLeaveWorld(self, entity):
        raise self._entity is entity or AssertionError('Attempt to unregister unknown manager: {0}, registered: {1}'.format(entity, self._entity))
        self._unsubscribe()
        self._entity = None
        return

    def cleanup(self):
        self._eManager.clear()

    def _subscribeOn(self, entity):
        raise self._subscription is None or AssertionError('Attempt to override subscription')
        self._subscription = CompositeSubscription(EventSubscription(entity.eWaveAdded, self.eWaveAdded), EventSubscription(entity.eWaveRemoved, self.eWaveRemoved), EventSubscription(entity.eWaveStateChanged, self.eWaveStateChanged), EventSubscription(entity.eBomberStateChanged, self.eBomberStateChanged))
        self._subscription.subscribe()
        return

    def _unsubscribe(self):
        raise self._subscription or AssertionError('Subscription is None')
        self._subscription.unsubscribe()
        self._subscription = None
        return
Ejemplo n.º 11
0
 def __init__(self, features):
     self._model = features.require(Feature.GAME_MODEL).classTasks
     self._player = features.require(Feature.PLAYER_AVATAR)
     self._clientArena = features.require(Feature.CLIENT_ARENA)
     coachMgr = self._player.coachManager
     self._subscription = CompositeSubscription(
         EventSubscription(coachMgr.eObjectivesChanged,
                           self._updateCurrentObjectives),
         EventSubscription(coachMgr.eObjectiveProgressChanged,
                           self._updateObjectiveProgress),
         EventSubscription(coachMgr.eObjectiveProgressRawValueChanged,
                           self._updateObjectiveRawProgressValue),
         EventSubscription(self._player.eTacticalRespawnEnd,
                           self._updateCurrentObjectives))
     self._subscription.subscribe()
     if self._clientArena.isAllServerDataReceived():
         self._setupModel(None)
     else:
         self._clientArena.onNewAvatarsInfo += self._setupModel
     logger.debug('Plane type objectives data source initialized')
     return
Ejemplo n.º 12
0
 def __init__(self, features):
     self._db = features.require(Feature.DB_LOGIC)
     self._bigWorld = features.require(Feature.BIG_WORLD)
     self._model = features.require(Feature.GAME_MODEL).currentPlayerInfo
     self._playerAvatar = features.require(Feature.PLAYER_AVATAR)
     self._clientArena = features.require(Feature.CLIENT_ARENA)
     self._planesConfigurationsDB = features.require(
         Feature.PLANES_CONFIGURATIONS_DB)
     self._subscription = CompositeSubscription(
         EventSubscription(self._playerAvatar.onStateChanged,
                           self._onStateChanged),
         EventSubscription(self._playerAvatar.eTacticalRespawnEnd,
                           self._fillPlaneData),
         EventSubscription(self._clientArena.onAvatarPlaneTypeRankChanged,
                           self._onAvatarPlaneTypeRankChanged),
         EventSubscription(self._clientArena.onAvatarPlaneTypeRankChanged,
                           self._updatePlaneScoresData),
         EventSubscription(
             self._clientArena.onPlayerEconomicExtDataReceived,
             self._updatePlaneScoresData))
     self._subscription.subscribe()
     self._fellModel()
Ejemplo n.º 13
0
class PlayerInfoSource(DataSource):
    def __init__(self, features):
        self._db = features.require(Feature.DB_LOGIC)
        self._bigWorld = features.require(Feature.BIG_WORLD)
        self._model = features.require(Feature.GAME_MODEL).currentPlayerInfo
        self._playerAvatar = features.require(Feature.PLAYER_AVATAR)
        self._clientArena = features.require(Feature.CLIENT_ARENA)
        self._planesConfigurationsDB = features.require(
            Feature.PLANES_CONFIGURATIONS_DB)
        self._subscription = CompositeSubscription(
            EventSubscription(self._playerAvatar.onStateChanged,
                              self._onStateChanged),
            EventSubscription(self._playerAvatar.eTacticalRespawnEnd,
                              self._fillPlaneData),
            EventSubscription(self._clientArena.onAvatarPlaneTypeRankChanged,
                              self._onAvatarPlaneTypeRankChanged),
            EventSubscription(self._clientArena.onAvatarPlaneTypeRankChanged,
                              self._updatePlaneScoresData),
            EventSubscription(
                self._clientArena.onPlayerEconomicExtDataReceived,
                self._updatePlaneScoresData))
        self._subscription.subscribe()
        self._fellModel()

    def _fellModel(self, *args, **kwargs):
        if self._clientArena.isAllServerDataReceived():
            self._setupModel(None)
        else:
            self._clientArena.onNewAvatarsInfo += self._setupModel
        self._fillPlaneData()
        return

    def _fillPlaneData(self, *args, **kwargs):
        avatarInfo = self._clientArena.getAvatarInfo(self._playerAvatar.id)
        settings = avatarInfo['settings']
        self._model.planeName = localizeAirplane(settings.airplane.name)
        self._model.planeLevel = settings.airplane.level
        self._model.planeGlobalID = self._playerAvatar.globalID
        self._model.id = self._playerAvatar.id
        self._model.planeType = settings.airplane.planeType
        self._model.teamIndex = self._playerAvatar.teamIndex
        if self._clientArena.isAllServerDataReceived():
            self._updatePlaneTypeRank()

    def _setupModel(self, newInfos):
        avatarInfo = self._clientArena.getAvatarInfo(self._playerAvatar.id)
        self._model.clanName = unicode(avatarInfo.get('clanAbbrev', ''))
        self._model.nickName = unicode(
            avatarInfo.get('playerName', 'unknown name'))
        self._model.squadIndex = avatarInfo.get('squadID', 0)
        self._model.state = getLogicState(avatarInfo)
        self._updatePlaneTypeRank()
        self._updatePlayerPlaneScoresData()

    def _onStateChanged(self, oldState, state):
        avatarInfo = self._clientArena.getAvatarInfo(self._playerAvatar.id)
        self._model.state = getLogicState(avatarInfo)

    def _onAvatarPlaneTypeRankChanged(self, avatarID, *args, **kwargs):
        if avatarID == self._bigWorld.player().id:
            self._updatePlaneTypeRank()

    def _updatePlaneTypeRank(self):
        id_ = self._bigWorld.player().id
        avatarInfo = self._clientArena.avatarInfos[id_]
        settings = avatarInfo['settings']
        planeType = settings.airplane.planeType
        self._model.rank = avatarInfo['planeTypeRank'][planeType]

    def _updatePlaneScoresData(self, avatarID, *args, **kwargs):
        """Update score data for all avatar planes.
         Is called when avatar rank is changed and when new battle points received from server
        """
        if avatarID == self._bigWorld.player().id:
            self._updatePlayerPlaneScoresData()

    def _updatePlayerPlaneScoresData(self):
        avatarInfo = self._clientArena.avatarInfos[self._bigWorld.player().id]
        economics = avatarInfo['economics']
        planeTypeRanks = avatarInfo['planeTypeRank']
        pointsByPlanes = economics['pointsByPlanes']
        if not pointsByPlanes:
            globalID = avatarInfo['airplaneInfo']['globalID']
            planeID = self._planesConfigurationsDB.getAirplaneConfiguration(
                globalID).planeID
            pointsByPlanes = [(planeID, 0)]
        for planeID, battlePoints in pointsByPlanes:
            planeData = self._db.getAircraftData(planeID)
            planeType = planeData.airplane.planeType
            scoreItem = self._model.planeScoresData.first(
                lambda e: e.planeID.get() == planeID)
            if scoreItem:
                scoreItem.battlePoints = battlePoints
                scoreItem.rankID = planeTypeRanks[planeType]
            else:
                self._model.planeScoresData.append(
                    planeID=planeID,
                    planeType=planeType,
                    planeName=localizeAirplane(planeData.airplane.name),
                    battlePoints=battlePoints,
                    rankID=planeTypeRanks[planeType])

    def dispose(self):
        self._subscription.unsubscribe()
        self._subscription = None
        self._clientArena.onNewAvatarsInfo -= self._setupModel
        self._playerAvatar = None
        self._clientArena = None
        self._model = None
        return
Ejemplo n.º 14
0
class PlayerSource(DataSource):
    def __init__(self, features):
        self._db = features.require(Feature.DB_LOGIC)
        self._model = features.require(Feature.GAME_MODEL).player
        self._playerAvatar = features.require(Feature.PLAYER_AVATAR)
        self._clientArena = features.require(Feature.CLIENT_ARENA)
        self._gameEnv = features.require(Feature.GAME_ENVIRONMENT)
        self._input = features.require(Feature.INPUT)
        self._playerAvatar.eTacticalSpectator += self._reFillModel
        self._input.eBattleModeChange += self._onSetBattleMod
        self._battleMod = BATTLE_MODE.COMBAT_MODE
        self._log = getLogger(self)
        self._fellModel()

    def _fellModel(self):
        if self._clientArena.isAllServerDataReceived():
            self._setupModel(None)
        else:
            self._clientArena.onNewAvatarsInfo += self._setupModel
        self._fillPlaneData()
        return

    def _reFillModel(self, *args, **kwargs):
        self._setupModel(None)
        self._fillPlaneData()
        return

    def __subscribe(self):
        self._subscription = CompositeSubscription(
            EventSubscription(self._playerAvatar.eUpdateHealth,
                              self._onUpdateHealth),
            EventSubscription(self._playerAvatar.onStateChanged,
                              self._onStateChanged),
            EventSubscription(self._playerAvatar.eTacticalRespawnEnd,
                              self._fillPlaneData),
            EventSubscription(self._gameEnv.ePlayerGunnerChangedTurret,
                              self._updateModelShootingDistance))
        self._subscription.subscribe()

    def _onSetBattleMod(self, bState):
        if self._battleMod == BATTLE_MODE.GUNNER_MODE or bState == BATTLE_MODE.GUNNER_MODE:
            self._battleMod = bState
            self._updateModelShootingDistance()

    def _updateModelShootingDistance(self, *args, **kwargs):
        self._model.effectiveShootingDistance = self._getGunnerShootingDistance(
        ) if self._battleMod == BATTLE_MODE.GUNNER_MODE else self._getMainArmamentShootingDistance(
        )
        self._model.shootingDistanceMax = self._getGunnerShootingDistance(
        ) if self._battleMod == BATTLE_MODE.GUNNER_MODE else self._getMainArmamentShootingDistanceMax(
        )
        self._log.debug(
            'new shooting distance effective: %s, new shooting distance max: %s',
            self._model.effectiveShootingDistance,
            self._model.shootingDistanceMax)

    def _getMainArmamentShootingDistance(self):
        playerGlobalID = self._playerAvatar.globalID
        return self._db.getShootingDistanceEffective(playerGlobalID)

    def _getMainArmamentShootingDistanceMax(self):
        playerGlobalID = self._playerAvatar.globalID
        return self._db.getShootingDistanceMax(playerGlobalID)

    def _getGunnerShootingDistance(self):
        gunner = self._playerAvatar.controlledGunner
        return gunner.shootDistance

    def _fillPlaneData(self, *args, **kwargs):
        avatarInfo = self._clientArena.getAvatarInfo(self._playerAvatar.id)
        playerGlobalID = self._playerAvatar.globalID
        settings = avatarInfo['settings']
        self._updateModelShootingDistance()
        self._model.planeName = localizeAirplane(settings.airplane.name)
        self._model.planeLevel = settings.airplane.level
        self._model.planeGlobalID = playerGlobalID
        self._model.planeType = settings.airplane.planeType
        self._model.planeTypeName = PREBATTLE_PLANE_TYPE_NAME[
            settings.airplane.planeType]
        self._model.planePreviewIcon = settings.airplane.previewIconPath
        self._model.planeId = self._playerAvatar.objTypeID
        self._model.planeStatus = self._getPlaneStatus()
        self._model.teamIndex = self._playerAvatar.teamIndex
        self._model.isReconnected = bool(self._playerAvatar.reconnected)

    def _getPlaneStatus(self):
        planeID = self._playerAvatar.objTypeID
        isPremium = self._db.isPlanePremium(planeID)
        isElite = planeID in self._playerAvatar.elitePlanes
        planeStatus = PLANE_CLASS.PREMIUM if isPremium else isElite * PLANE_CLASS.ELITE or PLANE_CLASS.REGULAR
        return planeStatus

    def _setupModel(self, newInfos):
        self.__subscribe()
        id = self._playerAvatar.id
        avatarInfo = self._clientArena.getAvatarInfo(id)
        self._model.id = id
        self._model.clanName = unicode(avatarInfo.get('clanAbbrev', ''))
        self._model.nickName = unicode(
            avatarInfo.get('playerName', 'unknown name'))
        self._model.health = int(ceil(self._playerAvatar.health))
        self._model.healthMax = int(ceil(self._playerAvatar.maxHealth))
        self._model.squadIndex = avatarInfo.get('squadID', 0)
        self._model.state = getLogicState(avatarInfo)

    def _onUpdateHealth(self, health, lastDamagerID, oldValue):
        self._model.health = int(ceil(health))

    def _onStateChanged(self, oldState, state):
        avatarInfo = self._clientArena.getAvatarInfo(self._playerAvatar.id)
        self._model.state = getLogicState(avatarInfo)

    def dispose(self):
        self._clientArena.onNewAvatarsInfo -= self._setupModel
        self._playerAvatar.eTacticalSpectator -= self._reFillModel
        self._subscription.unsubscribe()
        self._subscription = None
        self._input.eBattleModeChange -= self._onSetBattleMod
        self._gameEnv = None
        self._playerAvatar = None
        self._clientArena = None
        self._model = None
        return
Ejemplo n.º 15
0
 def _subscribeOn(self, entity):
     raise self._subscription is None or AssertionError('Attempt to override subscription')
     self._subscription = CompositeSubscription(EventSubscription(entity.eWaveAdded, self.eWaveAdded), EventSubscription(entity.eWaveRemoved, self.eWaveRemoved), EventSubscription(entity.eWaveStateChanged, self.eWaveStateChanged), EventSubscription(entity.eBomberStateChanged, self.eBomberStateChanged))
     self._subscription.subscribe()
     return
Ejemplo n.º 16
0
class PlaneTypeObjectivesDataSource(DataSource):
    """Data source for PlaneTypeObjectives model
    """
    def __init__(self, features):
        self._model = features.require(Feature.GAME_MODEL).classTasks
        self._player = features.require(Feature.PLAYER_AVATAR)
        self._clientArena = features.require(Feature.CLIENT_ARENA)
        coachMgr = self._player.coachManager
        self._subscription = CompositeSubscription(
            EventSubscription(coachMgr.eObjectivesChanged,
                              self._updateCurrentObjectives),
            EventSubscription(coachMgr.eObjectiveProgressChanged,
                              self._updateObjectiveProgress),
            EventSubscription(coachMgr.eObjectiveProgressRawValueChanged,
                              self._updateObjectiveRawProgressValue),
            EventSubscription(self._player.eTacticalRespawnEnd,
                              self._updateCurrentObjectives))
        self._subscription.subscribe()
        if self._clientArena.isAllServerDataReceived():
            self._setupModel(None)
        else:
            self._clientArena.onNewAvatarsInfo += self._setupModel
        logger.debug('Plane type objectives data source initialized')
        return

    def _setupModel(self, newInfos):
        self._clientArena.onNewAvatarsInfo -= self._setupModel
        self._updateCurrentObjectives()

    def _updateCurrentObjectives(self, *args, **kwargs):
        """Update current plane objectives.
        Should be called when objectives received from server or
        when avatar changed plane and new objectives are active now
        """
        self._model.classTasks.clean()
        coachMgr = self._player.coachManager
        for objective in coachMgr.getCurrentPlaneObjectives():
            self._model.classTasks.append(
                id=objective.id,
                title=objective.model.client.name.locale,
                countDescription=objective.model.client.countDescription.
                locale,
                description=objective.model.client.description.locale,
                progress=objective.progressCurrent,
                maxProgress=objective.progressMax,
                value=objective.progressRawValue,
                requiredValue=objective.getNextProgressBound())

    def _updateObjectiveProgress(self, planeType, objectiveID, progress, *args,
                                 **kwargs):
        """Handle objective progress update on eObjectiveProgressChanged event
        """
        objectiveData = self._player.coachManager.getObjectiveByID(objectiveID)
        objectiveModel = self._model.classTasks.first(
            lambda e: e.id.get() == objectiveID)
        if objectiveModel:
            objectiveModel.progress = progress
            objectiveModel.requiredValue = objectiveData.getNextProgressBound()

    def _updateObjectiveRawProgressValue(self, planeType, objectiveID,
                                         progressRawValue, *args, **kwargs):
        """Handle objective progress update on eObjectiveProgressChanged event
        """
        objectiveModel = self._model.classTasks.first(
            lambda e: e.id.get() == objectiveID)
        if objectiveModel:
            objectiveModel.value = progressRawValue

    def dispose(self):
        self._subscription.unsubscribe()
        self._subscription = None
        self._player = None
        self._clientArena = None
        self._model = None
        return
class SectorsGameEffectsSource(DataSource):
    def __init__(self, features):
        self._logger = BWLogging.getLogger(self.__class__.__name__)
        self._model = features.require(
            Feature.GAME_MODEL).domination.sectorsGameEffects
        self._clientArena = features.require(Feature.CLIENT_ARENA)
        self._db = features.require(Feature.DB_LOGIC)
        self._playerAvatar = features.require(Feature.PLAYER_AVATAR)
        self._gameMode = self._clientArena.gameMode
        self._disableBomberCallbacks = {}
        self._subscription = CompositeSubscription(
            EDSubscription(self.gameMode, AC_EVENTS.BOMBERS_LAUNCHED,
                           self._onBombersLaunched),
            EDSubscription(self.gameMode, AC_EVENTS.BOMBER_ATTACK_NOTIFIED,
                           self._onBomberAttackNotified),
            EDSubscription(self.gameMode, AC_EVENTS.BOMBER_BOMBS_DROPPED,
                           self._onBomberBombsDropped),
            EDSubscription(self.gameMode, AC_EVENTS.BOMBERS_DIED,
                           self._onBombersDied),
            EDSubscription(self.gameMode, AC_EVENTS.BOMBER_IN_WAVE_DIED,
                           self._onBomberInWaveDied),
            EDSubscription(self.gameMode.rocketV2Manager,
                           AC_EVENTS.ROCKET_V2_EFFECT_STARTED,
                           self._onRocketEffectStarted),
            EDSubscription(self.gameMode.rocketV2Manager,
                           AC_EVENTS.ROCKET_V2_EFFECT_ENDED,
                           self._onRocketEffectEnded),
            EventSubscription(self._clientArena.onReceiveMarkerMessage,
                              self._onReceiveMarkerMessage))
        self.gameMode.addEventHandler(
            AC_EVENTS.ROCKET_V2_TARGET_SECTOR_CHANGED,
            self._onRocketEffectSectorChanged)
        if self.gameMode.isReady:
            self._setupModel()
        else:
            self.gameMode.eGameModeReady += self._setupModel

    def _setupModel(self, *args, **kwargs):
        for record in self._clientArena.gameActionsManager.activeASWaves:
            state = WAVE_STATE_TO_HUD_STATE[record['state']]
            self._processASWave(record['sectorID'], record['targetID'],
                                record['teamIndex'], record['waveID'],
                                record['bomberIDsStates'], record['startTime'],
                                state)

        self._subscription.subscribe()

    @property
    def gameMode(self):
        """Game mode instance
        @rtype: ArenaHelpers.GameModes.AreaConquest.ACGameModeClient.ACGameModeClient
        """
        return self._gameMode

    def _onBombersLaunched(self, sectorIdent, targetSectorIdent, teamIndex,
                           waveID, bomberIDsStates, startTime, *args,
                           **kwargs):
        bomberIDs = [bomber['id'] for bomber in bomberIDsStates]
        self._logger.debug(
            "onBombersLaunched: sectorID = '{0}', targetID = '{1}', teamIndex = {2}, waveID = '{3}', bomberIDs = {4}, startTime = {5}"
            .format(sectorIdent, targetSectorIdent, teamIndex, waveID,
                    bomberIDs, startTime))
        self._processASWave(sectorIdent, targetSectorIdent, teamIndex, waveID,
                            bomberIDsStates, startTime,
                            BOMBERS_WAVE_STATE.INTRO_FLIGHT)

    def _processASWave(self, sectorIdent, targetSectorIdent, teamIndex, waveID,
                       bomberIDsStates, startTime, state):
        arenaTypeData = self._gameMode.arenaTypeData
        sector = arenaTypeData.sectors.sectors[sectorIdent]
        influenceSettings = sector.bomberDispatcher.influenceBySectors[
            targetSectorIdent]
        splineSettings = influenceSettings.splinesByTeams[teamIndex]
        spline = self._db.getSpline(splineSettings.name)
        points = spline.getBasePoints()
        startPoint = self._makePos(points[0].x, points[0].z)
        endPoint = self._makePos(points[-1].x, points[-1].z)
        actionPointIndex = splineSettings.actionPointIndex
        globalID = arenaTypeData.gameModeSettings.airStrike.globalIDByLevel[
            self._playerAvatar.battleLevel]
        maxSpeed = _performanceCharacteristics_db.airplanes[globalID].maxSpeed
        curSpeed = speedToMovement(maxSpeed) * WORLD_SCALING / 3.6
        dist = points[0].distTo(points[actionPointIndex])
        startDelay = 2
        flyingTime = dist / curSpeed
        arenaTime = startTime - self._playerAvatar.arenaStartTime
        strikeTime = int(arenaTime + flyingTime + startDelay)
        self._logger.debug(
            'Bombing time estimation: arenaTime = {0}, startDelay = {1}, flyingTime = {2}'
            .format(arenaTime, startDelay, flyingTime))
        waveTeamIndex = getClientTeamIndex(teamIndex,
                                           self._playerAvatar.teamIndex)
        self._appendASWave(sectorIdent, targetSectorIdent, waveTeamIndex,
                           waveID, startPoint, endPoint, strikeTime, state,
                           bomberIDsStates)

    def _onBomberInWaveDied(self, sectorIdent, waveID, bomberID):
        bomberEffect = self._model.airStrikes.first(
            lambda a: a.waveID.get() == waveID)
        if bomberEffect:
            bomberIDStruct = bomberEffect.bomberIDsStates.first(
                lambda d: d.id.get() == bomberID)
            if bomberIDStruct:
                bomberEffect.bomberIDsStates.splice(bomberIDStruct)

    def _onBomberAttackNotified(self, sectorID, waveID, bomberID, waveSize,
                                aliveBombers, *args, **kwargs):
        self._logger.debug(
            "_onBombersAttackNotified: sectorID = '{0}', waveID = '{1}', waveSize = {2}, aliveBombers = {3}"
            .format(sectorID, waveID, waveSize, aliveBombers))
        waveModel = self._model.airStrikes.first(
            lambda a: a.waveID.get() == waveID)
        if waveModel:
            waveModel.strikeState = BOMBERS_WAVE_STATE.BOMBING
            bomberModel = waveModel.bomberIDsStates.first(
                lambda a: a.id.get() == bomberID)
            if bomberModel:
                bomberModel.state = BOMBERS_WAVE_STATE.BOMBING

    def _onBomberBombsDropped(self, sectorID, waveID, bomberID, waveSize,
                              aliveBombers, *args, **kwargs):
        arenaTypeData = self._gameMode.arenaTypeData
        delay = arenaTypeData.gameModeSettings.airStrike.markersDelayByLevel[
            self._playerAvatar.battleLevel]
        model = self._model.airStrikes.first(
            lambda a: a.waveID.get() == waveID)
        self._disableBomberCallbacks[bomberID] = BigWorld.callback(
            delay, lambda: self.disableBomber(model, bomberID))

    def disableBomber(self, model, bomberID):
        def checkIfReadyToSplice(list):
            for item in list:
                if item.state.get() is not BOMBERS_WAVE_STATE.OUTRO_FLIGHT:
                    return False

            return True

        def checkIfSomebodyIsBombing(list):
            for item in list:
                if item.state.get() is BOMBERS_WAVE_STATE.BOMBING:
                    return True

            return False

        if model:
            bomberModel = model.bomberIDsStates.first(
                lambda a: a.id.get() == bomberID)
            if bomberModel:
                bomberModel.state = BOMBERS_WAVE_STATE.OUTRO_FLIGHT
            if checkIfReadyToSplice(model.bomberIDsStates):
                model.strikeState = BOMBERS_WAVE_STATE.OUTRO_FLIGHT
                waveID = model.waveID.get()
                if self._model.airStrikes.first(
                        lambda a: a.waveID.get() == waveID):
                    self._model.airStrikes.splice(model)
            elif checkIfSomebodyIsBombing(model.bomberIDsStates):
                model.strikeState = BOMBERS_WAVE_STATE.BOMBING
            else:
                model.strikeState = BOMBERS_WAVE_STATE.INTRO_FLIGHT

    def _onBombersDied(self, waveID, *args, **kwargs):
        self._logger.debug("onBombersDied: waveID = '{0}'".format(waveID))
        model = self._model.airStrikes.first(
            lambda a: a.waveID.get() == waveID)
        if model:
            for bomber in model.bomberIDsStates:
                bomber.state = BOMBERS_WAVE_STATE.OUTRO_FLIGHT

            model.strikeState = BOMBERS_WAVE_STATE.OUTRO_FLIGHT
            self._model.airStrikes.splice(model)

    def _onRocketEffectStarted(self, id, sectorIdent, targetSectorIdent,
                               startPosition, endPosition, teamIndex,
                               flyingTime):
        startTime = BigWorld.serverTime() - BigWorld.player().arenaStartTime
        startSectorPosition = self._getPosBySectorId(sectorIdent)
        endSectorPosition = self._getPosBySectorId(targetSectorIdent)
        self._model.rockets.append(
            id=id,
            sectorID=sectorIdent,
            targetSectorID=targetSectorIdent,
            startPoint=self._makePos(startSectorPosition.x,
                                     startSectorPosition.z),
            endPoint=self._makePos(endSectorPosition.x, endSectorPosition.z),
            teamIndex=teamIndex,
            flyingTime=flyingTime,
            startTime=startTime)

    def _onRocketEffectSectorChanged(self, id, newTargetSectorIdent):
        startSectorPosition = self._getPosBySectorId(id)
        endSectorPosition = self._getPosBySectorId(newTargetSectorIdent)
        for rocketEffect in self._model.rockets:
            if rocketEffect.sectorID.get() == id:
                rocketEffect.startPoint = self._makePos(
                    startSectorPosition.x, startSectorPosition.z)
                rocketEffect.endPoint = self._makePos(endSectorPosition.x,
                                                      endSectorPosition.z)
                rocketEffect.targetSectorID = newTargetSectorIdent
                break

    def _onReceiveMarkerMessage(self, senderID, posX, posZ, messageStringID,
                                fromQueue):
        self._model.selectedPoint = self._makePos(posX, posZ)

    def _onRocketEffectEnded(self, id):
        model = self._model.rockets.first(lambda a: a.id.get() == id)
        if model:
            self._model.rockets.splice(model)

    def _makePos(self, x, y):
        return {'x': x, 'y': y}

    def _getPosBySectorId(self, sectorId):
        sectorData = self._getSectorByID(sectorId)
        return sectorData.entity.position

    def _checkSectorInSectors(self, sectorId):
        return sectorId in self.gameMode.sectors

    def _getSectorByID(self, sectorId):
        """ACSectorClient instance
        @rtype: ArenaHelpers.GameModes.AreaConquest.ACSectorClient.ACSectorClient
        """
        return self.gameMode.sectors[sectorId]

    def _appendASWave(self, sectorID, targetID, teamIndex, waveID, startPoint,
                      endPoint, strikeTime, state, bomberIDsStates):
        item = self._model.airStrikes.append(sectorID=sectorID,
                                             targetSectorID=targetID,
                                             teamIndex=teamIndex,
                                             waveID=waveID,
                                             startPoint=startPoint,
                                             endPoint=endPoint,
                                             strikeTime=strikeTime,
                                             strikeState=state)
        for bomber in bomberIDsStates:
            item.bomberIDsStates.appendSilently(id=bomber['id'], state=state)

        item.bomberIDsStates.finishAppending()

    def dispose(self):
        for item in self._disableBomberCallbacks.itervalues():
            BigWorld.cancelCallback(item)

        self._disableBomberCallbacks.clear()
        self.gameMode.eGameModeReady -= self._setupModel
        self.gameMode.removeEventHandler(
            AC_EVENTS.ROCKET_V2_TARGET_SECTOR_CHANGED,
            self._onRocketEffectSectorChanged)
        self._subscription.unsubscribe()
        self._logger = None
        self._model = None
        self._clientArena = None
        self._db = None
        self._playerAvatar = None
        self._gameMode = None
        self._subscription = None
        return
Ejemplo n.º 18
0
class ExternalModifiers(AvatarControllerBase):
    def __init__(self, owner, consumables, equipment, crewSkills):
        AvatarControllerBase.__init__(self, owner)
        self.__skillConditions = SkillConditions(owner, SKILL_EVENT)
        self.__objects = {
            OBJ_GROUPS.CREW: [
                CrewSkills(owner, obj, self.__skillConditions, index)
                for index, obj in enumerate(crewSkills)
            ],
            OBJ_GROUPS.CONSUMABLES:
            [ConsumableEquipmentFeaturedObject(obj) for obj in consumables],
            OBJ_GROUPS.EQUIPMENT: [
                EquipmentFeaturedObject(obj, getCrewSkillsID(crewSkills))
                for obj in equipment
            ],
            OBJ_GROUPS.CAMOUFLAGE: [
                CamouflageFeatureObject(owner.camouflageBonusSchemeName,
                                        owner.isCamouflageSpecializedForCurMap)
            ]
        }
        self.__specializationIdToObj = {}
        for crewMember in self.__objects[OBJ_GROUPS.CREW]:
            self.__specializationIdToObj[
                crewMember.specializationID] = crewMember

        self.eModifiersChanged = Event.Event()
        self.modifiers = Modifiers()
        readyToUseSubscriptions = (
            EventSubscription(c.eReadyToUse, self._onConsumableReadyToUse)
            for c in self.__objects[OBJ_GROUPS.CONSUMABLES])
        self._subscription = CompositeSubscription(*readyToUseSubscriptions)
        if IS_CELLAPP:
            self._subscription.extend(
                EventSubscription(self._owner.eDestruction, self.onOwnerDeath))
        self._subscription.subscribe()

    def getFeatureObjects(self, featureObjectClass):
        return self.__objects.get(featureObjectClass, None)

    def destroy(self):
        self._subscription.unsubscribe()
        self._subscription = None
        AvatarControllerBase.destroy(self)
        for crewMember in self.__objects[OBJ_GROUPS.CREW]:
            crewMember.destroy()

        self.__objects.clear()
        self.__specializationIdToObj.clear()
        self.eModifiersChanged.clear()
        self.__skillConditions.destroy()
        return

    def onPartStateChanged(self, part):
        self.onPartsStateChanged([part])

    def onPartsStateChanged(self, parts):
        reCalc = False
        for part in parts:
            specID = getCrewSpecializationByName(
                part.partTypeData.componentType)
            if specID in self.__specializationIdToObj:
                self.__specializationIdToObj[specID].changeState(
                    part.logicalState)
                reCalc = True

        if reCalc:
            self.reCalc()

    def __findSlotIDByConsumableName(self, name):
        for slotID, slot in enumerate(self._owner.consumables):
            if slot['key'] != -1:
                consumable = db.DBLogic.g_instance.getConsumableByID(
                    slot['key'])
                if consumable:
                    if consumable.localizeTag == name:
                        return slotID
                else:
                    LOG_ERROR("Can't find consumable {c} description".format(
                        c=slot['key']))

    def isConsumablePresent(self, name):
        slotID = self.__findSlotIDByConsumableName(name)
        if slotID is not None:
            chargesCount = self._owner.consumables[slotID]['chargesCount']
            return chargesCount > 0 or chargesCount == -1
        else:
            return False

    def tryToUseConsumable(self, name):
        slotID = self.__findSlotIDByConsumableName(name)
        if slotID is not None:
            self.onUseConsumable(slotID)
        return

    def onUseConsumable(self, slotID):
        slot = self._owner.consumables[slotID]
        if slot['key'] != -1:
            consumable = self.__objects[OBJ_GROUPS.CONSUMABLES][slotID]
            from debug_utils import LOG_DEBUG_DEV
            LOG_DEBUG_DEV('onUseConsumable', slotID)
            if consumable.use(self._owner):
                self.reCalc()
                self._owner.publish(GameLogicEvents.CONSUMABLE_USED, slotID)

    def generateUsedConsumables(self):
        return []

    def generateUsableConsumables(self):
        for slotID, consumableData in enumerate(self._owner.consumables):
            if consumableData['key'] != -1:
                consumable = self.__objects[OBJ_GROUPS.CONSUMABLES][slotID]
                if not consumable.isUsable(self._owner):
                    continue
                consumableDb = db.DBLogic.g_instance.getConsumableByID(
                    consumableData['key'])
                if consumableDb.behaviour == 1:
                    consumableData['chargesCount'] = 0
                    continue
                yield slotID

    def onControllersCreated(self):
        crew = self.__objects.get(OBJ_GROUPS.CREW, [])
        for c in crew:
            c.afterRestore()

        for slotID, slotData in enumerate(self._owner.consumables):
            if slotData['key'] != -1:
                consumable = db.DBLogic.g_instance.getConsumableByID(
                    slotData['key'])
                if consumable.behaviour == 1:
                    self._owner.publish(GameLogicEvents.CONSUMABLE_USED,
                                        slotID)

    def restart(self):
        pass

    @property
    def crew(self):
        return self.__objects[OBJ_GROUPS.CREW]

    @property
    def consumables(self):
        """Consumables objects container
        :rtype: list[ConsumableEquipmentFeaturedObject]
        """
        return self.__objects[OBJ_GROUPS.CONSUMABLES]

    def reCalc(self):
        if __debug__ and IS_DEVELOPMENT:
            oldModifiers = self.modifiers.dump()
        self.modifiers.reset()
        for objGroup in self.__objects.values():
            for obj in objGroup:
                obj.applyObjMods(self.modifiers)

        self._owner.disguise = (self.modifiers.STEALTH - 1) * 100
        if __debug__ and IS_DEVELOPMENT:
            self.modifiers.printDiff(oldModifiers)
        self.eModifiersChanged(self.modifiers)

    def update1sec(self, ms):
        if not EntityStates.inState(self._owner, EntityStates.GAME):
            return
        if IS_DEVELOPMENT and BigWorld.globalData.get(
                'modifiersUpdateRequired',
                False) and self._owner.__class__.__name__ == 'Avatar':
            LOG_DEBUG(self._owner.id, 'reload request')
            BigWorld.globalData['modifiersUpdateRequired'] = False
            for crewMember in self.__objects[OBJ_GROUPS.CREW]:
                crewMember.reload()

            wasChanged = True
        else:
            wasChanged = False
        for c in self.__objects[OBJ_GROUPS.CONSUMABLES]:
            if c.update1sec():
                wasChanged = True

        for crewMember in self.__objects[OBJ_GROUPS.CREW]:
            if crewMember.update1sec():
                wasChanged = True

        if wasChanged:
            self.reCalc()

    def onParentSetState(self, stateID, data):
        LOG_DEBUG('Mods.onParentSetState', EntityStates.getStateName(stateID))
        if stateID == EntityStates.GAME:
            for crewMember in self.__objects[OBJ_GROUPS.CREW]:
                crewMember.initGame()

    def getTargetSkillModsActivity(self, crew_member):
        return EnemySkillObserver.get_target_skill_mods_activity(
            self, crew_member)

    @staticmethod
    def getTargetSkillModValue(crew_member, modsActivity):
        return EnemySkillObserver.get_target_skill_mod_value(
            crew_member, modsActivity)

    def backup(self):
        if OBJ_GROUPS.CREW not in self.__objects:
            return None
        else:
            res = [c.backup() for c in self.__objects[OBJ_GROUPS.CREW]]
            res.append(self.__skillConditions.backup())
            return res

    def restore(self, container):
        if container is None:
            return
        else:
            self.__skillConditions.restore(container.pop())
            crew = self.__objects.get(OBJ_GROUPS.CREW)
            if not crew:
                return
            for c, crewMember in zip(container, crew):
                crewMember.restore(c)

            return

    def onOwnerRespawn(self, *args, **kwargs):
        """Handler for Avatar.eRespawn event
        """
        currentTime = BigWorld.time()
        needUpdate = any([
            consumable.onOwnerRespawn(currentTime)
            for consumable in self.consumables
        ])
        if needUpdate:
            self.reCalc()

    def onOwnerDeath(self, *args, **kwargs):
        """Handler for Avatar.eDestruction event
        """
        currentTime = BigWorld.time()
        for consumable in self.consumables:
            consumable.onOwnerDestruction(currentTime)

    def _onConsumableReadyToUse(self, consumable):
        if consumable.isAutoUsable and consumable.isUsable(self._owner):
            self._owner.schedulePartAutoFix(consumable.autoRepairPartType)
Ejemplo n.º 19
0
class ACGameModeClient(GameModeClient.GameModeClient):
    updateEventsMap = {
        ARENA_UPDATE.UPDATE_AC_POINTS:
        AC_ARENA_UPDATE_EVENTS.UPDATE_AC_POINTS,
        ARENA_UPDATE.UPDATE_GLOBAL_COUNTERS:
        AC_ARENA_UPDATE_EVENTS.UPDATE_GLOBAL_COUNTERS,
        ARENA_UPDATE.UPDATE_RESOURCE_POINTS:
        AC_ARENA_UPDATE_EVENTS.UPDATE_RESOURCE_POINTS,
        ARENA_UPDATE.CHANGE_DYNAMIC_TIME:
        AC_ARENA_UPDATE_EVENTS.CHANGE_DYNAMIC_TIME,
        ARENA_UPDATE.AC_SECTOR_PERMANENT_LOCK:
        AC_ARENA_UPDATE_EVENTS.AC_SECTOR_PERMANENT_LOCK,
        ARENA_UPDATE.AC_ACTION_MESSAGE:
        AC_ARENA_UPDATE_EVENTS.AC_ACTION_MESSAGE,
        ARENA_UPDATE.AC_SECTORS_STATUS:
        AC_ARENA_UPDATE_EVENTS.AC_SECTORS_STATUS,
        ARENA_UPDATE.AC_GAME_TICK:
        AC_ARENA_UPDATE_EVENTS.AC_GAME_TICK,
        ARENA_UPDATE.AC_BATTLE_EVENT:
        AC_ARENA_UPDATE_EVENTS.AC_BATTLE_EVENT,
        ARENA_UPDATE.AC_ROCKET_V2_LAUNCHED:
        AC_ARENA_UPDATE_EVENTS.AC_ROCKET_V2_LAUNCHED,
        ARENA_UPDATE.AC_ROCKET_V2_HIT_TARGET:
        AC_ARENA_UPDATE_EVENTS.AC_ROCKET_V2_HIT_TARGET,
        ARENA_UPDATE.AC_ROCKET_V2_TARGET_OBJECT_CHANGED:
        AC_ARENA_UPDATE_EVENTS.AC_ROCKET_V2_TARGET_OBJECT_CHANGED,
        ARENA_UPDATE.AC_BOMBER_IN_WAVE_DIED:
        AC_ARENA_UPDATE_EVENTS.AC_BOMBER_IN_WAVE_DIED,
        ARENA_UPDATE.AC_BOMBER_DISPATCHER_TARGET_SECTOR_CHANGED:
        AC_ARENA_UPDATE_EVENTS.AC_BOMBER_DISPATCHER_TARGET_SECTOR_CHANGED
    }

    def __init__(self, clientArena):
        super(ACGameModeClient, self).__init__(clientArena)
        self._scoreGlobal = (0, 0)
        self._globalCounters = {}
        self._sectors = {}
        self._currentTick = 0
        self._currentTickStartedAt = self.player.arenaStartTime
        self._globalTime = 0
        self._dynamicTime = 0
        self._isReady = False
        self._eManager = EventManager()
        self.eGameModeReady = Event(self._eManager)
        self._rocketV2Manager = RocketV2Manager.RocketV2Manager(self)
        self._signalFlaresManager = SignalFlaresManager.SignalFlaresManager(
            self)
        self._waveInfoManager = WaveInfoManager(self)
        self._lastPlayerManager = LastPlayerManager(self)
        self._pendingEvents = []
        self.createSectorsData()
        self.registerArenaUpdateEvents(self.updateEventsMap)
        gameActionsManager = self.clientArena.gameActionsManager
        self._subscription = CompositeSubscription(
            EventSubscription(gameActionsManager.eWaveAdded,
                              self._onASWaveAdded),
            EventSubscription(gameActionsManager.eWaveRemoved,
                              self._onASWaveRemoved),
            EventSubscription(gameActionsManager.eWaveStateChanged,
                              self._onASWaveStateChanged),
            EventSubscription(gameActionsManager.eBomberStateChanged,
                              self._onASBomberStateChanged))
        self._subscription.subscribe()

    @property
    def isReady(self):
        return self._isReady

    @property
    def rocketV2Manager(self):
        """
        @rtype: RocketV2Manager.RocketV2Manager
        """
        return self._rocketV2Manager

    @property
    def scoreGlobal(self):
        """Global game score
        @rtype: (int, int)
        """
        return self._scoreGlobal

    @property
    def sectors(self):
        """Sectors dict
        @rtype: dict[basestring, ACSectorClient.ACSectorClient]
        """
        raise self.isReady or AssertionError(
            'Attempt to get sectors data while GameMode is not ready')
        return self._sectors

    @property
    def currentTick(self):
        """Current game tick number
        @rtype: int
        """
        return self._currentTick

    @property
    def currentTickStartedAt(self):
        """Time when current tick started by BigWorld.serverTime()
        @rtype: float
        """
        return self._currentTickStartedAt

    @property
    def arenaTimeRemaining(self):
        """battle time remaining
        @rtype: float
        """
        return self.player.arenaStartTime + self.arenaTypeData.gameModeSettings.battleDuration - BigWorld.serverTime(
        )

    @property
    def waveInfoManager(self):
        """
        @rtype: WaveInfoManager.WaveInfoManager
        """
        return self._waveInfoManager

    @property
    def uiSettings(self):
        return self.arenaTypeData.gameModeSettings.uiSettings

    @property
    def gameModeName(self):
        return GAME_MODE.NAMES[self.clientArena.gameModeEnum]

    @eventHandler(AC_ARENA_UPDATE_EVENTS.AC_BATTLE_EVENT)
    def onBattleEvent(self, payload, *args, **kwargs):
        self._logDebug(
            ':onUpdateACSBattleEvent: onBattleEvent'.format(payload))
        battleEventId = payload
        self.dispatch(AC_EVENTS.BATTLE_EVENT, battleEventId)

    @eventHandler(AC_ARENA_UPDATE_EVENTS.UPDATE_AC_POINTS)
    def onUpdateACPoints(self, payload, *args, **kwargs):
        points = tuple(payload)
        self._logDebug(':onUpdateACPoints: points={0}'.format(points))
        maxPoints = self._arenaTypeData.gameModeSettings.pointsToWin
        self._scoreGlobal = (min(points[0],
                                 maxPoints), min(points[1], maxPoints))
        self.dispatch(AC_EVENTS.GLOBAL_SCORE_UPDATED, self.scoreGlobal)

    @eventHandler(AC_ARENA_UPDATE_EVENTS.CHANGE_DYNAMIC_TIME)
    def onChangeDynamicTime(self, payload, *args, **kwargs):
        time = payload
        oldTime = self._dynamicTime
        self._dynamicTime = time
        self.dispatch(AC_EVENTS.DYNAMIC_TIMER_UPDATE, time, oldTime)

    @eventHandler(AC_ARENA_UPDATE_EVENTS.AC_SECTOR_PERMANENT_LOCK)
    def onSectorPermanentLock(self, payload, *args, **kwargs):
        sectorId = payload
        self.dispatch(AC_EVENTS.SECTOR_PERMANENT_LOCK, sectorId)

    @eventHandler(AC_ARENA_UPDATE_EVENTS.UPDATE_GLOBAL_COUNTERS)
    def onUpdateGlobalCounters(self, payload, *args, **kwargs):
        counters = payload
        self._logDebug(
            ':onUpdateGlobalCounters: counters={0}'.format(counters))
        self._globalCounters = counters
        self.dispatch(AC_EVENTS.GLOBAL_COUNTERS_UPDATED, self._globalCounters)

    @eventHandler(AC_ARENA_UPDATE_EVENTS.UPDATE_RESOURCE_POINTS)
    def onUpdateResourcePoints(self, payload, *args, **kwargs):
        totalPoints, killerID, victimID, pointsInc = payload
        self._logDebug(':onUpdateResourcePoints: {},{},{},{}'.format(
            totalPoints, killerID, victimID, pointsInc))
        self.dispatch(AC_EVENTS.RESOURCE_POINTS_UPDATED, totalPoints, killerID,
                      victimID, pointsInc)

    @eventHandler(AC_ARENA_UPDATE_EVENTS.AC_SECTORS_STATUS)
    def onACSectorStatus(self, payload, *args, **kwargs):
        self._logDebug(':onACSectorStatus: payload={0}'.format(payload))
        sectorID, sectorPoints, capturePoints = payload
        sector = self.sectors[sectorID]
        sector.updateCapturePoints(sectorPoints)
        self.dispatch(AC_EVENTS.SECTOR_CAPTURE_POINTS_CHANGED, sector.ident,
                      sector.capturePointsByTeams)

    @eventHandler(AC_ARENA_UPDATE_EVENTS.AC_ACTION_MESSAGE)
    def onACActionMessage(self, payload, *args, **kwargs):
        self._logDebug(':onACActionMessage: payload={0}'.format(payload))
        action, teamIndex, avatarId, sectorId, tickNumber, points = payload
        settings = SETTINGS.ACTION_SETTINGS.get(action)
        if not settings:
            self._logError(
                ':onACActionMessage: Unknown action got, id={0}'.format(
                    action))
            return
        self.dispatch(AC_EVENTS.SECTOR_ACTION, sectorId, teamIndex, settings)
        if settings['sectorScore']:
            sector = self.sectors[sectorId]
            sector.addCapturePoints(teamIndex, points)
            self._logDebug(
                ':onACActionMessage: updated sector capture points: {0}'.
                format(sector.capturePointsByTeams))
            self.dispatch(AC_EVENTS.SECTOR_CAPTURE_POINTS_CHANGED,
                          sector.ident, sector.capturePointsByTeams)

    @eventHandler(AC_ARENA_UPDATE_EVENTS.AC_GAME_TICK)
    def onACGameTick(self, payload, *args, **kwargs):
        self._logDebug(':onACGameTick: payload={0}'.format(payload))
        tickNumber = payload
        self.dispatch(AC_EVENTS.GAME_MODE_TICK, tickNumber)
        self._currentTick = tickNumber + 1
        self._currentTickStartedAt = BigWorld.serverTime()

    @eventHandler(AC_ARENA_UPDATE_EVENTS.AC_ROCKET_V2_LAUNCHED)
    def onRocketV2Launched(self, payload, *args, **kwargs):
        launchPosition, targetPosition = Math.Vector3(), Math.Vector3()
        sectorIdent, launchPosition.x, launchPosition.y, launchPosition.z, targetID, targetPosition.x, targetPosition.y, targetPosition.z, flyingTime = payload
        self.dispatch(AC_EVENTS.ROCKET_V2_LAUNCHED, sectorIdent,
                      launchPosition, targetPosition, flyingTime)

    def onRocketV2TargetSectorChanged(self, sectorID, oldTargetID, newTargetID,
                                      *args, **kwargs):
        self.dispatch(AC_EVENTS.ROCKET_V2_TARGET_SECTOR_CHANGED, sectorID,
                      newTargetID)

    @eventHandler(AC_ARENA_UPDATE_EVENTS.AC_ROCKET_V2_TARGET_OBJECT_CHANGED)
    def onRocketV2TargetObjectChanged(self, payload, *args, **kwargs):
        sectorIdent, sectorTeamIndex, newTargetObjId = payload
        self.dispatch(AC_EVENTS.ROCKET_V2_TARGET_OBJECT_CHANGED, sectorIdent,
                      sectorTeamIndex, newTargetObjId)

    @eventHandler(AC_ARENA_UPDATE_EVENTS.AC_ROCKET_V2_HIT_TARGET)
    def onRocketV2HitTarget(self, payload, *args, **kwargs):
        sectorIdent, teamIndex, targetTeamObjectId, targetPositionX, targetPositionY, targetPositionZ, targetTeamIndex = payload
        self.dispatch(AC_EVENTS.ROCKET_V2_HIT_TARGET, sectorIdent, teamIndex,
                      targetTeamObjectId)

    @eventHandler(AC_ARENA_UPDATE_EVENTS.AC_BOMBER_IN_WAVE_DIED)
    def onBomberInWaveDied(self, payload):
        sectorIdent, waveID, bomberID = payload
        self.dispatch(AC_EVENTS.BOMBER_IN_WAVE_DIED, sectorIdent, waveID,
                      bomberID)

    @eventHandler(
        AC_ARENA_UPDATE_EVENTS.AC_BOMBER_DISPATCHER_TARGET_SECTOR_CHANGED)
    def onBombersChangeTarget(self, payload):
        sectorIdent, newTargetSectorIdent = payload
        self.dispatch(AC_EVENTS.BOMBER_DISPATCHER_TARGET_SECTOR_CHANGED,
                      sectorIdent, newTargetSectorIdent)

    def createSectorsData(self):
        """Create sectors data using arena settings
        """
        for sectorId, settings in self.arenaTypeData.sectors.sectors.iteritems(
        ):
            entity = next(
                (sector
                 for sector in ACSector.entities if sector.ident == sectorId),
                None)
            if entity:
                self._sectors[
                    sectorId] = sector = ACSectorClient.ACSectorClient(
                        settings, entity)
                sector.eStateChanged += self.onSectorStateChanged
                sector.eRocketV2TargetSectorIDChanged += self.onRocketV2TargetSectorChanged

        self._checkIsReady()
        return

    def getPointsInTick(self, tickNumber=None):
        """Return Points in tick
        @param tickNumber: tick number
        """
        tickNumber = tickNumber or self.currentTick
        score = [0, 0]
        for sector in self.sectors.itervalues():
            if sector.teamIndex in (TEAM_ID.TEAM_0, TEAM_ID.TEAM_1):
                score[sector.teamIndex] += sector.getPointsInTick(tickNumber)

        return score

    def getTickPeriod(self):
        """Return tick period
        """
        period = self.arenaTypeData.gameModeSettings.globalTickPeriod
        if self.teamSuperiority(TEAM_ID.TEAM_0) or self.teamSuperiority(
                TEAM_ID.TEAM_1):
            period = self.arenaTypeData.gameModeSettings.superiorityGlobalTickPeriod
        return period

    def capturedSectors(self, teamIndex):
        """Return captured sectors
        """
        capturedSectors = 0
        for sector in self._sectors.itervalues():
            if not sector.isCapturable:
                continue
            if sector.teamIndex == teamIndex:
                capturedSectors += 1

        return capturedSectors

    def teamSuperiority(self, teamIndex):
        """Check capture sectors by team
        """
        sectors = 0
        capturedSectors = 0
        for sector in self._sectors.itervalues():
            if not sector.isCapturable:
                continue
            sectors += 1
            if sector.teamIndex == teamIndex:
                capturedSectors += 1

        return sectors == capturedSectors

    def checkSectorForLock(self, ident):
        if ident in self._sectors:
            return self._sectors[ident].isLockForBattle
        return False

    def onSectorStateChanged(self, ident, oldState, state, *args, **kwargs):
        """Event handler for state changed event
        @param ident: Sector identifier
        @type state: BWUserTypesCommon.ACSectorState.ACSectorState
        @type oldState: BWUserTypesCommon.ACSectorState.ACSectorState
        """
        self.dispatch(AC_EVENTS.SECTOR_STATE_CHANGED, ident, oldState.state,
                      oldState.teamIndex, state.state, state.teamIndex,
                      state.nextStateTimestamp)

    def _checkIsReady(self):
        if self._isReady:
            return
        self._isReady = all((ident in self._sectors
                             for ident in self.arenaTypeData.sectors.sectors))
        if self._isReady:
            self._processSuspendedEvents()
            self.eGameModeReady()

    def onACSectorCreated(self, entity):
        """Callback from sector entity on enter world event
        @type entity: ACSector
        """
        raise entity.ident in self.arenaTypeData.sectors.sectors or AssertionError(
            "Unexpected sector created: '{0}', arena: {1}".format(
                entity.ident, self.arenaTypeData.typeName))
        settings = self.arenaTypeData.sectors.sectors[entity.ident]
        self._sectors[entity.ident] = sector = ACSectorClient.ACSectorClient(
            settings, entity)
        sector.eStateChanged += self.onSectorStateChanged
        self._checkIsReady()

    @property
    def lastPlayerManager(self):
        return self._lastPlayerManager

    def dispatch(self, event, *args, **kwargs):
        if not self.isReady:
            self._suspendEvent(event, args, kwargs)
            self._logDebug(
                "Suspended event processing while game mode is not ready: event = '{0}', args = {1}, kwargs = {2}"
                .format(event, args, kwargs))
            return
        super(ACGameModeClient, self).dispatch(event, *args, **kwargs)

    def destroy(self):
        self._subscription.unsubscribe()
        self._subscription = None
        self._waveInfoManager.destroy()
        self._lastPlayerManager.destroy()
        self._eManager.clear()
        self._rocketV2Manager.destroy()
        self._signalFlaresManager.destroy()
        self.clear()
        super(ACGameModeClient, self).destroy()
        return

    def _suspendEvent(self, event, args, kwargs):
        self._pendingEvents.append((event, args, kwargs))

    def _processSuspendedEvents(self):
        for event, args, kwargs in self._pendingEvents:
            self.dispatch(event, *args, **kwargs)

        self._pendingEvents[:] = []

    def _onASWaveAdded(self, record, *args, **kwargs):
        """Handler for GameActionsManager.eWaveAdded event
        :param record: AIR_STRIKE_WAVE_RECORD
        """
        self.dispatch(AC_EVENTS.BOMBERS_LAUNCHED, record['sectorID'],
                      record['targetID'], record['teamIndex'],
                      record['waveID'], record['bomberIDsStates'],
                      record['startTime'])

    def _onASWaveRemoved(self, waveID, *args, **kwargs):
        """Handler for GameActionsManager.eWaveRemoved event
        :param waveID: Unique wave identifier 
        """
        self.dispatch(AC_EVENTS.BOMBERS_DIED, waveID)

    def _onASWaveStateChanged(self, record, stateOld, state, *args, **kwargs):
        """Handler for GameActionsManager.eWaveStateChanged event
        :param record: AIR_STRIKE_WAVE_RECORD
        :param stateOld: Old state value
        :param state: New state value
        """
        if state == AIR_STRIKE_WAVE_STATE.ATTACK_IN_PROGRESS and stateOld == AIR_STRIKE_WAVE_STATE.BOMBS_DROPPED:
            self.dispatch(AC_EVENTS.BOMBERS_ATTACK_STARTED, record['sectorID'],
                          record['waveID'], record['size'],
                          len(record['bomberIDsStates']))

    def _onASBomberStateChanged(self, record, bomberID, stateOld, state, *args,
                                **kwargs):
        """Handler for GameActionsManager.eBomberStateChanged event
        :param record: AIR_STRIKE_WAVE_RECORD
        :param bomberID: Unique bomber id
        :param stateOld: Old state value
        :param state: New state value
        """
        if state == AIR_STRIKE_WAVE_STATE.ATTACK_NOTIFIED and stateOld == AIR_STRIKE_WAVE_STATE.INTRO_FLIGHT:
            self.dispatch(AC_EVENTS.BOMBER_ATTACK_NOTIFIED, record['sectorID'],
                          record['waveID'], bomberID, record['size'],
                          len(record['bomberIDsStates']))
        elif state == AIR_STRIKE_WAVE_STATE.BOMBS_DROPPED and stateOld == AIR_STRIKE_WAVE_STATE.ATTACK_NOTIFIED:
            self.dispatch(AC_EVENTS.BOMBER_BOMBS_DROPPED, record['sectorID'],
                          record['waveID'], bomberID, record['size'],
                          len(record['bomberIDsStates']))
class AirStrikeDefeatedEventProvider(object):
    """
    Provides with event when air strike bombers are defeated with player participation before they started to attack
    
    @type _eventCandidates: dict[int, EventCandidate]
    """
    def __init__(self, gameEnvironment, gameMode):
        """
        @type gameEnvironment: GameEnvironment.GameEnvironment
        @type gameMode: ArenaHelpers.GameModes.AreaConquest.ACGameModeClient.ACGameModeClient
        """
        self._gameEnvironment = gameEnvironment
        self._gameMode = gameMode
        self._eventCandidates = {}
        self.__waveDiedCallbacks = {}
        self.eAirStrikeDefeated = Event()
        self._subscribe()

    def destroy(self):
        self.__clearAllCallbacks()
        self._unsubscribe()
        self.eAirStrikeDefeated.clear()
        self._gameEnvironment = None
        self._gameMode = None
        return

    def _subscribe(self):
        self._subscription = CompositeSubscription(
            EventSubscription(self._gameEnvironment.eAvatarHealthChange,
                              self._onAvatarHealthChanged),
            EDSubscription(self._gameMode, AC_EVENTS.BOMBERS_LAUNCHED,
                           self._onACBombersWaveLaunched),
            EDSubscription(self._gameMode, AC_EVENTS.BOMBERS_DIED,
                           self._onACBombersWaveDied),
            EDSubscription(self._gameMode, AC_EVENTS.BOMBERS_ATTACK_STARTED,
                           self._onACBombersAttackStarted))
        self._subscription.subscribe()

    def _unsubscribe(self):
        self._subscription.unsubscribe()
        self._subscription = None
        return

    def __clearCB(self, waveID):
        if waveID in self.__waveDiedCallbacks:
            BigWorld.cancelCallback(self.__waveDiedCallbacks[waveID])
            del self.__waveDiedCallbacks[waveID]

    def __clearAllCallbacks(self):
        for waveID, callback in self.__waveDiedCallbacks.iteritems():
            BigWorld.cancelCallback(callback)

        self.__waveDiedCallbacks = {}

    def _onAvatarHealthChanged(self, entity, *args, **kwargs):
        if entity.lastDamagerID != BigWorld.player().id:
            return
        for waveID, candidate in self._eventCandidates.iteritems():
            if candidate.isDamagedByPlayer:
                continue
            if entity.id in candidate.bomberIDs:
                candidate.isDamagedByPlayer = True
                break

    def _onACBombersWaveLaunched(self, sectorID, targetID, teamIndex, waveID,
                                 bomberIDsStates, startTime, *args, **kwargs):
        if BigWorld.player().teamIndex == teamIndex:
            return
        bomberIDs = [bomber['id'] for bomber in bomberIDsStates]
        self._eventCandidates[waveID] = EventCandidate(waveID, bomberIDs,
                                                       targetID, teamIndex)

    def _onACBombersAttackStarted(self, sectorID, waveID, waveSize,
                                  aliveBombers, *args, **kwargs):
        if waveID in self._eventCandidates:
            del self._eventCandidates[waveID]

    def _onACBombersWaveDied(self, waveID, *args, **kwargs):
        if waveID in self._eventCandidates:
            if self._eventCandidates[waveID].isDamagedByPlayer:
                if waveID not in self.__waveDiedCallbacks:
                    onACBombersWaveDiedCallback = partial(
                        self._onACBombersWaveDied, waveID, *args, **kwargs)
                    self.__waveDiedCallbacks[waveID] = BigWorld.callback(
                        0.5, onACBombersWaveDiedCallback)
                    return
                targetID = self._eventCandidates[waveID].targetID
                if not self._eventCandidates[
                        waveID].teamIndex == self._gameMode.sectors[
                            targetID].teamIndex:
                    self.eAirStrikeDefeated()
                self.__clearCB(waveID)
            del self._eventCandidates[waveID]
Ejemplo n.º 21
0
class EntitiesSource(DataSource):
    def __init__(self, features):
        self._logger = BWLogging.getLogger(self.__class__.__name__)
        self._model = features.require(Feature.GAME_MODEL).entities
        self._gameEnvironment = features.require(Feature.GAME_ENVIRONMENT)
        self._clientArena = features.require(Feature.CLIENT_ARENA)
        self._playerAvatar = features.require(Feature.PLAYER_AVATAR)
        self._db = features.require(Feature.DB_LOGIC)
        self._planeConfigurationsDB = features.require(
            Feature.PLANES_CONFIGURATIONS_DB)
        self._playerTeamIndex = self._playerAvatar.teamIndex
        self._playerAvatar.eTacticalSpectator += self._hideAvatarData
        self._teamObjectsSource = TeamObjectsSource(self._model.teamObjects,
                                                    features)
        self._tempVisibleObjectsSource = TempVisibleObjectsSource(
            self._model, features)
        self._lastTacticalSpectatorID = self._playerAvatar.id
        self._sources = {}
        self._subscribe()

    def _subscribe(self):
        self._subscription = CompositeSubscription(
            EventSubscription(self._clientArena.onAvatarPlaneTypeRankChanged,
                              self._updateAvatarPlaneTypeRank),
            EventSubscription(self._clientArena.onAvatarPlaneTypeRankChanged,
                              self._updatePlaneScoresData),
            EventSubscription(
                self._clientArena.onPlayerEconomicExtDataReceived,
                self._updatePlaneScoresData),
            EventSubscription(self._clientArena.onAvatarChangedPlane,
                              self._updateAvatarPlaneTypeRank),
            EventSubscription(self._clientArena.onAvatarEnterWorld,
                              self._onAvatarEnterWorld),
            EventSubscription(self._clientArena.onAvatarLeaveWorld,
                              self._onAvatarLeaveWorld),
            EventSubscription(self._clientArena.onEconomicPlayersPoints,
                              self._onPlayersPoints),
            EventSubscription(self._clientArena.onUpdatePlayerStats,
                              self._onUpdatePlayerStats))
        self._subscription.subscribe()
        if self._clientArena.isAllServerDataReceived():
            self._onNewAvatarsInfo(None)
        else:
            self._clientArena.onNewAvatarsInfo += self._onNewAvatarsInfo
        return

    def _onNewAvatarsInfo(self, avatarInfos):
        self._clientArena.onNewAvatarsInfo -= self._onNewAvatarsInfo
        for avatarInfo in self._clientArena.avatarInfos.values():
            id_ = avatarInfo['avatarID']
            if avatarInfo['isNPC'] and avatarInfo[
                    'NPCType'] == ACNPCTypes.Bomber:
                bomberModel = self._onNewBomber(id_, avatarInfo)
                self._checkBombersWithEntity(id_, bomberModel)
            else:
                self._onNewAvatar(id_, avatarInfo)

    def _checkBombersWithEntity(self, bomberID, bomberModel):
        entity = BigWorld.entities.get(bomberID)
        if entity is not None:
            if entity.inWorld:
                self._updateAvatarOnEnterWorld(entity, bomberModel)
        return

    def _hideAvatarData(self, *args, **kwargs):
        model = self._getEntityModel(self._lastTacticalSpectatorID)
        if model is not None:
            entity = BigWorld.entities.get(self._lastTacticalSpectatorID)
            if entity is not None:
                model.inWorld = entity.inWorld
        model = self._getEntityModel(self._playerAvatar.id)
        if model is not None:
            model.inWorld = False
        self._lastTacticalSpectatorID = self._playerAvatar.id
        return

    def _onNewAvatar(self, id, avatarInfo):
        entity = BigWorld.entities.get(id)
        if entity:
            self._addAvatarFromEntity(entity, avatarInfo, id)
        else:
            self._addAvatarFromInfo(avatarInfo, id)
        self._updatePlaneScoresData(id)

    def _onNewBomber(self, id, avatarInfo):
        LOG_DEBUG('EntitySource :: _onNewBomber', id)
        settings = avatarInfo.get('settings')
        return self._model.bombers.append(
            id=id,
            planeName=localizeAirplane(settings.airplane.name),
            playerName=avatarInfo['playerName'],
            teamIndex=getClientTeamIndex(avatarInfo['teamIndex'],
                                         self._playerAvatar.teamIndex),
            maxHealth=int(ceil(avatarInfo['maxHealth'])),
            inWorld=False)

    def _addAvatarFromEntity(self, entity, avatarInfo, id):
        if id == self._playerAvatar.id:
            return
        avatarModel = self._addAvatarFromInfo(avatarInfo, id)
        self._updateAvatarOnEnterWorld(entity, avatarModel)

    def _addAvatarFromInfo(self, avatarInfo, id):
        settings = avatarInfo.get('settings')
        if not settings:
            globalID = avatarInfo['airplaneInfo']['globalID']
            import _airplanesConfigurations_db
            planeID = _airplanesConfigurations_db.getAirplaneConfiguration(
                globalID).planeID
            settings = self._db.getAircraftData(planeID)
        untypedName = avatarInfo.get('playerName', '')
        globalID = avatarInfo['airplaneInfo']['globalID']
        currentPlaneType = settings.airplane.planeType
        currentRankID = avatarInfo['planeTypeRank'][currentPlaneType]
        if type(untypedName) is unicode:
            playerName = untypedName
        else:
            playerName = unicode(untypedName, 'utf-8')
        return self._model.avatars.append(
            id=id,
            clanName=unicode(avatarInfo.get('clanAbbrev', '')),
            playerName=playerName,
            planeGlobalID=globalID,
            isDefender=bool(avatarInfo.get('defendSector')),
            isBot=bool(avatarInfo.get('databaseID') == 0),
            planeType=settings.airplane.planeType,
            planeName=localizeAirplane(settings.airplane.name),
            planeLevel=settings.airplane.level,
            previewIconPath=settings.airplane.previewIconPath,
            teamIndex=getClientTeamIndex(avatarInfo['teamIndex'],
                                         self._playerAvatar.teamIndex),
            squadIndex=avatarInfo['squadID'],
            maxHealth=int(ceil(avatarInfo['maxHealth'])),
            points=avatarInfo['economics']['totalBattlePoints'],
            inWorld=False,
            state=getLogicState(avatarInfo),
            isLost=checkLost(avatarInfo),
            rankID=currentRankID)

    def _onUpdatePlayerStats(self, avatarInfo):
        self._updateStateAvatarInfo(avatarInfo)

    def _onPlayersPoints(self, data):
        for id, points in data.iteritems():
            avatarModel = self._model.avatars.first(lambda e: e.id.get() == id)
            if avatarModel:
                avatarModel.points = points

    def _updateAvatarOnEnterWorld(self, entity, avatarModel):
        avatarModel.inWorld = True
        from Bomber import Bomber
        if not isinstance(entity, Bomber):
            self._updatePlaneIfChanged(entity, avatarModel)
            source = AvatarSource(avatarModel, entity, self._playerTeamIndex)
        else:
            source = EntitySource(avatarModel,
                                  entity,
                                  self._playerTeamIndex,
                                  isBomber=True)
            LOG_DEBUG('EntitySource :: _updateAvatarOnEnterWorld')
        if entity.id in self._sources:
            self._sources[entity.id].dispose()
        self._sources[entity.id] = source

    def _updatePlaneIfChanged(self, entity, avatarModel):
        settings = entity.settings
        newPlaneName = localizeAirplane(settings.airplane.name)
        if newPlaneName != avatarModel.planeName.get():
            avatarModel.planeName = newPlaneName
            avatarModel.planeType = settings.airplane.planeType
            avatarModel.planeLevel = settings.airplane.level

    def _onAvatarEnterWorld(self, entity):
        if not entity.id not in self._sources:
            raise AssertionError
            avatarModel = self._getEntityModel(entity.id)
            avatarModel is not None and self._updateAvatarOnEnterWorld(
                entity, avatarModel)
        return

    def _onAvatarLeaveWorld(self, entity):
        avatarModel = self._getEntityModel(entity.id)
        if avatarModel is not None:
            avatarModel.inWorld = False
            source = self._sources.get(entity.id)
            if source:
                source.dispose()
                del self._sources[entity.id]
        return

    def _getEntityModel(self, id):
        avatarModel = self._model.avatars.first(lambda e: e.id.get() == id)
        if avatarModel is None:
            avatarModel = self._model.bombers.first(lambda e: e.id.get() == id)
        return avatarModel

    def _updateStateAvatarInfo(self, avatarInfo):
        if avatarInfo:
            avatarID = avatarInfo['avatarID']
            avatarModel = self._model.avatars.first(
                lambda e: e.id.get() == avatarID)
            if avatarModel:
                logicState = getLogicState(avatarInfo)
                avatarModel.state = logicState
                isLost = checkLost(avatarInfo)
                if avatarModel.isLost.get() != isLost:
                    avatarModel.isLost = isLost

    def _updateAvatarPlaneTypeRank(self, avatarID, *args, **kwargs):
        """Update rank for avatar in model.
        :param avatarID: Identifier of Avatar to update 
        """
        avatarInfo = self._clientArena.avatarInfos[avatarID]
        settings = avatarInfo.get('settings')
        if not settings:
            globalID = avatarInfo['airplaneInfo']['globalID']
            import _airplanesConfigurations_db
            planeID = _airplanesConfigurations_db.getAirplaneConfiguration(
                globalID).planeID
            settings = self._db.getAircraftData(planeID)
        currentPlaneType = settings.airplane.planeType
        currentRankID = avatarInfo['planeTypeRank'][currentPlaneType]
        avatarModel = self._model.avatars.first(
            lambda e: e.id.get() == avatarID)
        if avatarModel:
            avatarModel.rankID = currentRankID

    def _updatePlaneScoresData(self, avatarID, *args, **kwargs):
        """Update score data for all avatar planes.
         Is called when avatar rank is changed and when new battle points received from server
        """
        avatarInfo = self._clientArena.avatarInfos[avatarID]
        economics = avatarInfo['economics']
        planeTypeRanks = avatarInfo['planeTypeRank']
        pointsByPlanes = economics['pointsByPlanes']
        if not pointsByPlanes:
            globalID = avatarInfo['airplaneInfo']['globalID']
            planeID = self._planeConfigurationsDB.getAirplaneConfiguration(
                globalID).planeID
            pointsByPlanes = [(planeID, 0)]
        avatarItem = self._model.avatars.first(
            lambda e: e.id.get() == avatarID)
        if not avatarItem:
            return
        for planeID, battlePoints in pointsByPlanes:
            planeData = self._db.getAircraftData(planeID)
            planeType = planeData.airplane.planeType
            scoreItem = avatarItem.planeScoresData.first(
                lambda e: e.planeID.get() == planeID)
            if scoreItem:
                scoreItem.battlePoints = battlePoints
                scoreItem.rankID = planeTypeRanks[planeType]
            else:
                avatarItem.planeScoresData.append(
                    planeID=planeID,
                    planeType=planeType,
                    planeName=localizeAirplane(planeData.airplane.name),
                    battlePoints=battlePoints,
                    rankID=planeTypeRanks[planeType])

    def dispose(self):
        self._subscription.subscribe()
        self._subscription = None
        self._clientArena.onNewAvatarsInfo -= self._onNewAvatarsInfo
        self._playerAvatar.eTacticalSpectator -= self._hideAvatarData
        self._teamObjectsSource.dispose()
        self._tempVisibleObjectsSource.dispose()
        for source in self._sources.itervalues():
            source.dispose()

        self._sources = {}
        return
Ejemplo n.º 22
0
class OutroSource(DataSource):
    def __init__(self, features):
        self._model = features.require(Feature.GAME_MODEL).outro
        self._db = features.require(Feature.DB_LOGIC)
        self._bigWorld = features.require(Feature.BIG_WORLD)
        self._economics = features.require(Feature.CLIENT_ECONOMICS)
        self._player = features.require(Feature.REAL_PLAYER_AVATAR)
        self._clientArena = features.require(Feature.CLIENT_ARENA)
        self._clientArena.onGameResultChanged += self._update
        self._economics.onUpdateBattlePoints += self._updatePlayerEconomics
        self._cachedTeammates = []
        self._updateRateSubscription = None
        self._isFirstBattleResultUpdate = True
        return

    def _update(self, gameResult, winState):
        playerTeamIndex = self._player.teamIndex
        enemyTeamIndex = 1 - self._player.teamIndex
        logger.debug('RESULT::::: {0}'.format(gameResult))
        if gameResult in GAME_RESULT_LOC_IDS:
            resIndex = 2 if winState == 2 else int(playerTeamIndex != winState)
            reason = GAME_RESULT_LOC_IDS[gameResult][resIndex]
            self._model.reason = reason
            logger.debug('Update: {0}, {1}, {2}, {3}'.format(
                gameResult, winState, playerTeamIndex, reason))
        self._model.winnerTeamIndex = winState
        self._updateBattleTime()
        scoreGlobal = self._clientArena.gameMode.scoreGlobal
        self._model.allyPoints = scoreGlobal[playerTeamIndex]
        self._model.enemyPoints = scoreGlobal[enemyTeamIndex]
        self._updatePlayerTeamRate()
        self._updatePlayerEconomics()
        if not self._updateRateSubscription:
            self._updateRateSubscription = CompositeSubscription(
                EventSubscription(self._clientArena.onEconomicEvents,
                                  self._updatePlayerTeamRate),
                EventSubscription(self._clientArena.onEconomicPlayersPoints,
                                  self._updatePlayerTeamRate))
            self._updateRateSubscription.subscribe()
        self._updateBestRankData()

    def _updateBattleTime(self):
        if self._isFirstBattleResultUpdate:
            battleTimeRaw = self._bigWorld.serverTime(
            ) - self._bigWorld.player().arenaStartTime + ARENA_WAIT4DRAW_DELAY
            self._model.goToHangarTime = int(battleTimeRaw + OUTRO_TIME +
                                             OUTRO_TIME_QUIT_DELAY + 0.5)
            self._model.battleTime = int(battleTimeRaw + 0.5)
        self._isFirstBattleResultUpdate = False

    def _updatePlayerTeamRate(self, *args, **kwargs):
        """Update model.playerLevel based player's on battle points
        """
        places = {}
        teammatesArray = self._getTeammatesArray()
        for avatarID in teammatesArray:
            avatarInfo = self._clientArena.avatarInfos[avatarID]
            battlePoints = avatarInfo['economics']['totalBattlePoints']
            planeType = self._db.getAircraftData(
                avatarInfo['bestRankPlaneID']).airplane.planeType
            rankID = avatarInfo['planeTypeRank'][planeType]
            bestRankOrderIndex = 0
            if rankID != RankModel.EMPTY_RANK_ID:
                bestRankOrderIndex = RankModel.getRankByID(rankID).orderIndex
            places.setdefault((bestRankOrderIndex, battlePoints),
                              []).append(avatarID)

        places = sorted(places.iteritems(),
                        key=lambda item: item[0],
                        reverse=True)
        playerPointsRate = None
        for place, (data, players) in enumerate(places, start=1):
            if self._player.id in players:
                playerPointsRate = place
                break

        raise playerPointsRate or AssertionError(
            'Sorting error, data: {}'.format(places))
        logger.debug('Update player points rate: {0}'.format(playerPointsRate))
        self._model.playerLevel = playerPointsRate
        return

    def _getTeammatesArray(self):
        """Return list with teammates avatarIDs
        :rtype: list[int]
        """
        if not self._cachedTeammates:
            self._cachedTeammates = []
            for avatarID, avatarInfo in self._clientArena.avatarInfos.iteritems(
            ):
                if not avatarInfo[
                        'isNPC'] and self._player.teamIndex == avatarInfo[
                            'teamIndex']:
                    self._cachedTeammates.append(avatarID)

        return self._cachedTeammates

    def _updateBestRankData(self):
        avatarInfo = self._clientArena.avatarInfos[self._player.id]
        bestPlaneID = avatarInfo['bestRankPlaneID']
        planeData = self._db.getAircraftData(bestPlaneID)
        planeType = planeData.airplane.planeType
        bestRankID = avatarInfo['planeTypeRank'][planeType]
        logger.debug('Best rank id = {0}, planeID = {1}'.format(
            bestRankID, bestPlaneID))
        self._model.bestPlane = localizeAirplane(planeData.airplane.name)
        self._model.bestClass = localizeLobby(
            PREBATTLE_PLANE_TYPE_NAME[planeType])
        self._model.bestPlaneType = planeType
        self._model.bestRank = bestRankID
        self._model.bestTasks.clean()
        for objective in self._player.coachManager.getPlaneTypeObjectives(
                planeType):
            self._model.bestTasks.append(
                id=objective.id,
                title=objective.model.client.name.locale,
                description=objective.model.client.description.locale,
                progress=objective.progressCurrent,
                maxProgress=objective.progressMax,
                value=objective.progressRawValue,
                requiredValue=objective.getNextProgressBound())

    def _updatePlayerEconomics(self, *args, **kwargs):
        """Update outro economics data
        """
        self._model.battlePoints = self._economics.battlePoints
        self._model.masteryPoints = self._economics.experience

    def dispose(self):
        if self._updateRateSubscription:
            self._updateRateSubscription.unsubscribe()
            self._updateRateSubscription = None
        self._economics.onUpdateBattlePoints -= self._updatePlayerEconomics
        self._clientArena.onGameResultChanged -= self._update
        self._model = None
        self._bigWorld = None
        return