class _PythonTimer(_TimerComponent):
    __slots__ = ('_timeInterval', '_startTime', '_finishTime', '__weakref__')

    def __init__(self, panel, typeID, viewID, totalTime):
        super(_PythonTimer, self).__init__(panel, typeID, viewID, totalTime)
        self._timeInterval = TimeInterval(1.0, self, '_tick')
        self._startTime = BigWorld.serverTime()
        if totalTime:
            self._finishTime = self._startTime + totalTime
        else:
            self._finishTime = 0

    def clear(self):
        self._timeInterval.stop()
        super(_PythonTimer, self).clear()

    def _startTick(self):
        if self._totalTime:
            timeLeft = max(0, self._finishTime - BigWorld.serverTime())
            if timeLeft:
                self._panel.as_setTimeSnapshotS(self._typeID, self._totalTime,
                                                timeLeft)
                self._timeInterval.start()

    def _stopTick(self):
        self._timeInterval.stop()

    def _tick(self):
        timeLeft = self._finishTime - BigWorld.serverTime()
        if timeLeft >= 0:
            self._panel.as_setTimeSnapshotS(self._typeID, self._totalTime,
                                            timeLeft)
        else:
            self.hide()
class PythonTimer(TimerComponent):
    __slots__ = ('_timeInterval', '__weakref__')

    def __init__(self, panel, typeID, viewID, totalTime):
        super(PythonTimer, self).__init__(panel, typeID, viewID, totalTime)
        self._timeInterval = TimeInterval(1.0, self, '_tick')

    def clear(self):
        self._timeInterval.stop()
        super(PythonTimer, self).clear()

    def _startTick(self):
        if self._totalTime:
            timeLeft = max(0, self._finishTime - BigWorld.serverTime())
            if timeLeft:
                self._setViewSnapshot(timeLeft)
                self._timeInterval.start()

    def _stopTick(self):
        self._timeInterval.stop()

    def _tick(self):
        timeLeft = self._finishTime - BigWorld.serverTime()
        if timeLeft >= 0:
            self._setViewSnapshot(timeLeft)
        else:
            self.hide()

    def _setViewSnapshot(self, timeLeft):
        raise NotImplementedError
Example #3
0
class _DistancePlugin(IPlugin):
    __slots__ = ('__weakref__', '_interval', '_distance')

    def __init__(self, parentObj):
        super(_DistancePlugin, self).__init__(parentObj)
        self._interval = None
        self._distance = 0
        return

    def start(self):
        self._interval = TimeInterval(_TARGET_UPDATE_INTERVAL, self, '_update')
        ctrl = g_sessionProvider.shared.crosshair
        raise ctrl is not None or AssertionError('Crosshair controller is not found')
        ctrl.onCrosshairViewChanged += self._onCrosshairViewChanged
        return

    def stop(self):
        if self._interval is not None:
            self._interval.stop()
            self._interval = None
        ctrl = g_sessionProvider.shared.crosshair
        if ctrl is not None:
            ctrl.onCrosshairViewChanged -= self._onCrosshairViewChanged
        return

    def _update(self):
        raise NotImplementedError

    def _onCrosshairViewChanged(self, viewID):
        raise NotImplementedError
class _PythonTimer(_TimerComponent):
    __slots__ = ('_timeInterval', '_startTime', '_finishTime', '__weakref__')

    def __init__(self, panel, typeID, viewID, totalTime):
        super(_PythonTimer, self).__init__(panel, typeID, viewID, totalTime)
        self._timeInterval = TimeInterval(1.0, self, '_tick')
        self._startTime = BigWorld.serverTime()
        if totalTime:
            self._finishTime = self._startTime + totalTime
        else:
            self._finishTime = 0

    def clear(self):
        self._timeInterval.stop()
        super(_PythonTimer, self).clear()

    def _startTick(self):
        if self._totalTime:
            timeLeft = max(0, self._finishTime - BigWorld.serverTime())
            if timeLeft:
                self._panel.as_setTimeSnapshotS(self._typeID, self._totalTime, timeLeft)
                self._timeInterval.start()

    def _stopTick(self):
        self._timeInterval.stop()

    def _tick(self):
        timeLeft = self._finishTime - BigWorld.serverTime()
        if timeLeft >= 0:
            self._panel.as_setTimeSnapshotS(self._typeID, self._totalTime, timeLeft)
        else:
            self.hide()
class _DistancePlugin(CrosshairPlugin):
    __slots__ = ('_interval', '_distance')

    def __init__(self, parentObj):
        super(_DistancePlugin, self).__init__(parentObj)
        self._interval = None
        self._distance = 0
        return

    def start(self):
        self._interval = TimeInterval(_TARGET_UPDATE_INTERVAL, self, '_update')
        ctrl = self.sessionProvider.shared.crosshair
        ctrl.onCrosshairViewChanged += self._onCrosshairViewChanged

    def stop(self):
        if self._interval is not None:
            self._interval.stop()
            self._interval = None
        ctrl = self.sessionProvider.shared.crosshair
        if ctrl is not None:
            ctrl.onCrosshairViewChanged -= self._onCrosshairViewChanged
        return

    def _update(self):
        raise NotImplementedError

    def _onCrosshairViewChanged(self, viewID):
        raise NotImplementedError
class PythonTimer(TimerComponent):
    __slots__ = ('_timeInterval', '__weakref__')

    def __init__(self, viewObject, typeID, viewID, totalTime, finishTime, startTime=None, interval=1.0, secondInRow=False, **kwargs):
        super(PythonTimer, self).__init__(viewObject, typeID, viewID, totalTime, finishTime, startTime, secondInRow=secondInRow, **kwargs)
        self._timeInterval = TimeInterval(interval, self, '_tick')

    def clear(self):
        self._timeInterval.stop()
        super(PythonTimer, self).clear()

    def _startTick(self):
        if self._totalTime:
            timeLeft = max(0, self._finishTime - BigWorld.serverTime())
            if timeLeft:
                self._setViewSnapshot(timeLeft)
                self._timeInterval.restart()

    def _stopTick(self):
        self._timeInterval.stop()

    def _tick(self):
        timeLeft = self._finishTime - BigWorld.serverTime()
        if timeLeft >= 0:
            self._setViewSnapshot(timeLeft)
        else:
            self.hide()

    def _setViewSnapshot(self, timeLeft):
        raise NotImplementedError
Example #7
0
class DebugController(IViewComponentsController):
    """Controller for the debug panel.
    
    This class starts internal update cycle and updates debug panel.
    In order to collect lagging info from near vehicles, these vehicle's ids
    should be provided from outside using special methods.
    """
    statsCollector = dependency.descriptor(IStatisticsCollector)

    def __init__(self):
        super(DebugController, self).__init__()
        self._debugPanelUI = None
        self._timeInterval = None
        return

    def getControllerID(self):
        return BATTLE_CTRL_ID.DEBUG

    def startControl(self):
        self._timeInterval = TimeInterval(_UPDATE_INTERVAL, self, '_update')
        self._timeInterval.start()

    def stopControl(self):
        self._timeInterval.stop()
        self._timeInterval = None
        self.clearViewComponents()
        return

    def setViewComponents(self, debugPanelUI):
        raise isinstance(debugPanelUI, IDebugPanel) or AssertionError
        self._debugPanelUI = debugPanelUI

    def clearViewComponents(self):
        self._debugPanelUI = None
        return

    def _update(self):
        replayCtrl = BattleReplay.g_replayCtrl
        if replayCtrl.isPlaying and not replayCtrl.isBattleSimulation and replayCtrl.fps > 0:
            fps = BigWorld.getFPS()[1]
            fpsReplay = int(replayCtrl.fps)
            ping = replayCtrl.ping
            isLaggingNow = replayCtrl.isLaggingNow
        else:
            fpsReplay = -1
            isLaggingNow = BigWorld.statLagDetected()
            ping = BigWorld.statPing()
            fps = BigWorld.getFPS()[1]
            self.statsCollector.update()
            if replayCtrl.isRecording:
                replayCtrl.setFpsPingLag(fps, ping, isLaggingNow)
        try:
            ping = int(ping)
            fps = int(fps)
        except (ValueError, OverflowError):
            return

        if self._debugPanelUI is not None:
            self._debugPanelUI.updateDebugInfo(int(ping), int(fps), isLaggingNow, fpsReplay=fpsReplay)
        return
Example #8
0
class DebugController(IViewComponentsController):
    """Controller for the debug panel.
    
    This class starts internal update cycle and updates debug panel.
    In order to collect lagging info from near vehicles, these vehicle's ids
    should be provided from outside using special methods.
    """

    def __init__(self):
        super(DebugController, self).__init__()
        self._debugPanelUI = None
        self._timeInterval = None
        return

    def getControllerID(self):
        return BATTLE_CTRL_ID.DEBUG

    def startControl(self):
        self._timeInterval = TimeInterval(_UPDATE_INTERVAL, self, '_update')
        self._timeInterval.start()

    def stopControl(self):
        self._timeInterval.stop()
        self._timeInterval = None
        self._debugPanelUI = None
        return

    def setViewComponents(self, debugPanelUI):
        raise isinstance(debugPanelUI, IDebugPanel) or AssertionError
        self._debugPanelUI = debugPanelUI

    def clearViewComponents(self):
        self._debugPanelUI = None
        return

    def _update(self):
        replayCtrl = BattleReplay.g_replayCtrl
        if replayCtrl.isPlaying and replayCtrl.fps > 0:
            fps = BigWorld.getFPS()[1]
            fpsReplay = int(replayCtrl.fps)
            ping = replayCtrl.ping
            isLaggingNow = replayCtrl.isLaggingNow
        else:
            fpsReplay = -1
            isLaggingNow = BigWorld.statLagDetected()
            ping = BigWorld.statPing()
            fps = BigWorld.getFPS()[1]
            g_statistics.update()
            if replayCtrl.isRecording:
                replayCtrl.setFpsPingLag(fps, ping, isLaggingNow)
        try:
            ping = int(ping)
            fps = int(fps)
        except (ValueError, OverflowError):
            return

        if self._debugPanelUI is not None:
            self._debugPanelUI.updateDebugInfo(int(ping), int(fps), isLaggingNow, fpsReplay=fpsReplay)
        return
Example #9
0
class DebugPanel(UIInterface):
    __UPDATE_INTERVAL = 0.01

    def __init__(self, parentUI):
        UIInterface.__init__(self)
        self.__ui = parentUI
        self.__timeInterval = None
        self.__performanceStats = _PerformanceStats()
        self.__performanceStats.populateUI(parentUI)

    def start(self):
        self.__timeInterval = TimeInterval(self.__UPDATE_INTERVAL, self, '_DebugPanel__update')
        self.__timeInterval.start()
        self.__update()

    def destroy(self):
        self.__performanceStats.disposeUI()
        self.__performanceStats = None
        self.__timeInterval.stop()

    def __update(self):
        player = BigWorld.player()
        if player is None or not hasattr(player, 'playerVehicleID'):
            return
        fps = 0
        recordedFps = -1
        ping = 0
        isLaggingNow = False
        replayCtrl = BattleReplay.g_replayCtrl
        if replayCtrl.isPlaying and replayCtrl.fps > 0:
            fps = BigWorld.getFPS()[1]
            recordedFps = replayCtrl.fps
            ping = replayCtrl.ping
            isLaggingNow = replayCtrl.isLaggingNow
        else:
            isLaggingNow = player.filter.isLaggingNow
            if not isLaggingNow:
                for v in BigWorld.entities.values():
                    if _isVehicleEntity(v):
                        if not v.isPlayer:
                            if v.isAlive() and isinstance(v.filter, BigWorld.WGVehicleFilter) and v.filter.isLaggingNow:
                                isLaggingNow = True
                                break

            ping = min(BigWorld.LatencyInfo().value[3] * 1000, 999)
            if ping < 999:
                ping = max(1, ping - 500.0 * constants.SERVER_TICK_LENGTH)
            fpsInfo = BigWorld.getFPS()
            from helpers.statistics import g_statistics
            g_statistics.update(fpsInfo, ping, isLaggingNow)
            fps = fpsInfo[1]
            if replayCtrl.isRecording:
                replayCtrl.setFpsPingLag(fps, ping, isLaggingNow)
        try:
            self.__performanceStats.updateDebugInfo(int(fps), int(ping), isLaggingNow, int(recordedFps))
        except:
            pass
Example #10
0
class DebugController(IViewComponentsController):
    statsCollector = dependency.descriptor(IStatisticsCollector)

    def __init__(self):
        super(DebugController, self).__init__()
        self._debugPanelUI = None
        self._timeInterval = None
        return

    def getControllerID(self):
        return BATTLE_CTRL_ID.DEBUG

    def startControl(self):
        self._timeInterval = TimeInterval(_UPDATE_INTERVAL, self, '_update')
        self._timeInterval.start()

    def stopControl(self):
        self._timeInterval.stop()
        self._timeInterval = None
        self.clearViewComponents()
        return

    def setViewComponents(self, debugPanelUI):
        self._debugPanelUI = debugPanelUI

    def clearViewComponents(self):
        self._debugPanelUI = None
        return

    def _update(self):
        replayCtrl = BattleReplay.g_replayCtrl
        if replayCtrl.isPlaying and not replayCtrl.isBattleSimulation and replayCtrl.fps > 0 or replayCtrl.isServerSideReplay:
            fps = BigWorld.getFPS()[1]
            fpsReplay = int(replayCtrl.fps)
            ping = replayCtrl.ping
            isLaggingNow = replayCtrl.isLaggingNow
        else:
            fpsReplay = -1
            isLaggingNow = BigWorld.statLagDetected()
            ping = BigWorld.statPing()
            fps = BigWorld.getFPS()[1]
            self.statsCollector.update()
            if replayCtrl.isRecording:
                replayCtrl.setFpsPingLag(fps, ping, isLaggingNow)
        try:
            ping = int(ping)
            fps = int(fps)
        except (ValueError, OverflowError):
            return

        if self._debugPanelUI is not None:
            self._debugPanelUI.updateDebugInfo(ping,
                                               fps,
                                               isLaggingNow,
                                               fpsReplay=fpsReplay)
        return
class TimerReload(object):

    def __init__(self):
        self.strTime = ''
        self.section = 'damageLog/timeReload/'
        self.currentTime = 0
        self.finishTime = 0
        self.data = None
        self.timerReloadAttacker = None

    def reset(self):
        self.strTime = ''
        self.section = 'damageLog/timeReload/'
        self.currentTime = 0
        self.finishTime = 0
        self.data = None
        if (self.timerReloadAttacker is not None) and self.timerReloadAttacker.isStarted:
            self.timerReloadAttacker.stop()

    def afterTimerReload(self):
        self.strTime = ''
        if (self.timerReloadAttacker is not None) and self.timerReloadAttacker.isStarted:
            self.timerReloadAttacker.stop()
        as_event('ON_TIMER_RELOAD')

    def currentTimeReload(self):
        self.data['timer'] = self.finishTime - BigWorld.serverTime()
        timeTextAfterReload = float(config.get(self.section + 'timeTextAfterReload'))
        if self.data['timer'] > 0:
            macroes = getValueMacroes(self.section, self.data)
            self.strTime = parser(config.get(self.section + 'formatTimer'), macroes)
        else:
            self.timerReloadAttacker.stop()
            if timeTextAfterReload > 0:
                self.timerReloadAttacker = TimeInterval(timeTextAfterReload, self, 'afterTimerReload')
                macroes = getValueMacroes(self.section, self.data)
                self.strTime = parser(config.get(self.section + 'formatTimerAfterReload'), macroes)
                self.timerReloadAttacker.start()
            else:
                self.strTime = ''
        as_event('ON_TIMER_RELOAD')

    def output(self):
        if (data.data['attackReasonID'] == 0) and (data.data['timer'] > 0):
            self.data = data.data.copy()
            macroes = getValueMacroes(self.section, self.data)
            self.strTime = parser(config.get(self.section + 'formatTimer'), macroes)
            as_event('ON_TIMER_RELOAD')
            self.finishTime = self.data['timer'] + BigWorld.serverTime()
            if (self.timerReloadAttacker is not None) and (self.timerReloadAttacker.isStarted):
                self.timerReloadAttacker.stop()
            self.timerReloadAttacker = TimeInterval(0.1, self, 'currentTimeReload')
            self.timerReloadAttacker.start()
Example #12
0
class _PythonUpdater(_ComponentUpdater):
    """
    This updater is used only in REPLAYS.
    It will use internal timer to tick every 0.05 second.
    This solution is necessary to display actual timeLeft, states, etc correctly
    during replay's timeWarp, rewind, start/stop, etc.
    """
    __slots__ = ('_timeInterval', '_startTime', '_finishTime', '__weakref__')

    def __init__(self, parentObj, totalTime, timeLeft, siegeState, engineState,
                 isSmooth):
        super(_PythonUpdater, self).__init__(parentObj, totalTime, timeLeft,
                                             siegeState, engineState, isSmooth)
        self._timeInterval = TimeInterval(0.05, self, '_tick')
        self._startTime = BigWorld.serverTime()
        self._finishTime = self._startTime + timeLeft

    def clear(self):
        self._timeInterval.stop()
        super(_PythonUpdater, self).clear()

    def _startTick(self):
        if self._siegeState in VEHICLE_SIEGE_STATE.SWITCHING:
            timeLeft = max(0, self._finishTime - BigWorld.serverTime())
            if timeLeft:
                self._updateSnapshot(timeLeft)
                self._timeInterval.start()
        else:
            self._updateSnapshot(self._timeLeft)
        self._isSmooth = False

    def _stopTick(self):
        self._timeInterval.stop()

    def _tick(self):
        timeLeft = self._finishTime - BigWorld.serverTime()
        if timeLeft >= 0 and self._engineState != 'destroyed':
            self._updateSnapshot(timeLeft)

    def _updateSnapshot(self, timeLeft):
        self._parentObj.as_switchSiegeStateSnapshotS(self._totalTime, timeLeft,
                                                     self._siegeState,
                                                     self._engineState,
                                                     self._isSmooth)
Example #13
0
class _PythonUpdater(_ComponentUpdater):
    __slots__ = ('_timeInterval', '_startTime', '_finishTime', '__weakref__')

    def __init__(self, parentObj, totalTime, timeLeft, siegeState, engineState,
                 isSmooth):
        super(_PythonUpdater, self).__init__(parentObj, totalTime, timeLeft,
                                             siegeState, engineState, isSmooth)
        self._timeInterval = TimeInterval(0.05, self, '_tick')
        self._startTime = BigWorld.serverTime()
        self._finishTime = self._startTime + timeLeft

    def clear(self):
        self._timeInterval.stop()
        super(_PythonUpdater, self).clear()

    def _startTick(self):
        if self._siegeState in VEHICLE_SIEGE_STATE.SWITCHING and not self._staticMode:
            timeLeft = max(0, self._finishTime - BigWorld.serverTime())
            if timeLeft:
                self._updateSnapshot(timeLeft)
                self._timeInterval.start()
        else:
            self._updateSnapshot(self._timeLeft)
        self._isSmooth = False

    def _stopTick(self):
        self._timeInterval.stop()

    def _tick(self):
        if self._staticMode:
            return
        timeLeft = self._finishTime - BigWorld.serverTime()
        if timeLeft >= 0 and self._engineState != 'destroyed':
            self._updateSnapshot(timeLeft)

    def _updateSnapshot(self, timeLeft):
        if self._staticMode:
            self._parentObj.as_setAutoSiegeModeStateS(self._siegeState,
                                                      self._engineState)
        else:
            self._parentObj.as_switchSiegeStateSnapshotS(
                self._totalTime, timeLeft, self._siegeState, self._engineState,
                self._isSmooth)
Example #14
0
class TimeTrackState(RepairState):
    __slots__ = ('_timer', '_nextTime', '__weakref__')

    def __init__(self, pointIndex, stateID, *actions):
        super(TimeTrackState, self).__init__(pointIndex, stateID, *actions)
        self._timer = None
        self._nextTime = 0
        return

    def destroy(self):
        self._destroyTimer()
        super(TimeTrackState, self).destroy()

    def setAction(self, action, nextActionTime):
        if action in self._actions:
            self._recreateTimer(nextActionTime)
            self._updateTime()
        else:
            self._destroyTimer()

    def _getTimeLeft(self):
        return max(0, round(self._nextTime - BigWorld.serverTime()))

    def _updateTime(self):
        self._ctrl.onTimerUpdated(self._pointIndex, self._stateID,
                                  self._getTimeLeft())

    def _createTimer(self, nextActionTime):
        self._nextTime = nextActionTime
        self._timer = TimeInterval(1, self, '_updateTime')
        self._timer.start()

    def _destroyTimer(self):
        if self._timer is not None:
            self._timer.stop()
            self._timer = None
        return

    def _recreateTimer(self, nextActionTime):
        self._destroyTimer()
        self._createTimer(nextActionTime)
Example #15
0
class TimeTrackState(RepairState):
    __slots__ = ('_timer', '_nextTime', '__weakref__')

    def __init__(self, pointIndex, stateID, *actions):
        super(TimeTrackState, self).__init__(pointIndex, stateID, *actions)
        self._timer = None
        self._nextTime = 0
        return

    def destroy(self):
        self._destroyTimer()
        super(TimeTrackState, self).destroy()

    def setAction(self, action, nextActionTime):
        if action in self._actions:
            self._recreateTimer(nextActionTime)
            self._updateTime()
        else:
            self._destroyTimer()

    def _getTimeLeft(self):
        return max(0, round(self._nextTime - BigWorld.serverTime()))

    def _updateTime(self):
        self._ctrl.onTimerUpdated(self._pointIndex, self._stateID, self._getTimeLeft())

    def _createTimer(self, nextActionTime):
        self._nextTime = nextActionTime
        self._timer = TimeInterval(1, self, '_updateTime')
        self._timer.start()

    def _destroyTimer(self):
        if self._timer is not None:
            self._timer.stop()
            self._timer = None
        return

    def _recreateTimer(self, nextActionTime):
        self._destroyTimer()
        self._createTimer(nextActionTime)
Example #16
0
class VehicleStateController(IBattleController):

    def __init__(self):
        super(VehicleStateController, self).__init__()
        self.__eManager = Event.EventManager()
        self.onVehicleStateUpdated = Event.Event(self.__eManager)
        self.onVehicleControlling = Event.Event(self.__eManager)
        self.onPostMortemSwitched = Event.Event(self.__eManager)
        self.onRespawnBaseMoving = Event.Event(self.__eManager)
        self.__cachedStateValues = {}
        self.__waitingTI = TimeInterval(VEHICLE_WAINING_INTERVAL, self, '_waiting')
        self.__vehicleID = 0
        self.__updater = None
        self.__isRqToSwitch = False
        self.__isInPostmortem = False
        self.__needInvalidate = False
        return

    def getControllerID(self):
        return BATTLE_CTRL_ID.OBSERVED_VEHICLE_STATE

    def startControl(self):
        pass

    def stopControl(self):
        if self.__waitingTI is not None:
            self.__waitingTI.stop()
            self.__waitingTI = None
        if self.__updater is not None:
            self.__updater.clear()
            self.__updater = None
        self.__vehicleID = 0
        self.__isRqToSwitch = False
        self.__isInPostmortem = False
        self.__eManager.clear()
        self.__cachedStateValues.clear()
        return

    @property
    def isInPostmortem(self):
        return self.__isInPostmortem

    def setPlayerVehicle(self, vehicleID):
        self.notifyStateChanged(VEHICLE_VIEW_STATE.PLAYER_INFO, vehicleID)
        self.__vehicleID = vehicleID
        self.__updater = _VehicleUpdater(self, self.__vehicleID)
        self.__waitingTI.start()

    def getControllingVehicle(self):
        vehicle = None
        if self.__vehicleID:
            vehicle = BigWorld.entity(self.__vehicleID)
        return vehicle

    def getControllingVehicleID(self):
        return self.__vehicleID

    def notifyStateChanged(self, stateID, value):
        if stateID == VEHICLE_VIEW_STATE.DEVICES:
            self.__cachedStateValues.setdefault(stateID, [])
            self.__cachedStateValues[stateID].append(value)
        else:
            self.__cachedStateValues[stateID] = value
        self.onVehicleStateUpdated(stateID, value)

    def getStateValue(self, stateID):
        return self.__cachedStateValues[stateID] if stateID in self.__cachedStateValues else None

    def refreshVehicleStateValue(self, stateID):
        if stateID in self.__cachedStateValues:
            self.onVehicleStateUpdated(stateID, self.__cachedStateValues[stateID])

    def invalidate(self, state, value, vehicleID=0):
        if vehicleID != 0 and vehicleID != self.__vehicleID:
            return
        else:
            isStateChangeHandled = False
            if self.__isRqToSwitch and self.__waitingTI.isStarted():
                self._waiting()
            if self.__updater is not None:
                isStateChangeHandled = self.__updater.handleStateChange(state, value)
            if not isStateChangeHandled:
                self.notifyStateChanged(state, value)
            return

    def switchToPostmortem(self, noRespawnPossible, respawnAvailable):
        self.__isRqToSwitch = False
        if avatar_getter.getPlayerVehicleID() == self.__vehicleID:
            if self.__updater is not None:
                self.__updater.stop()
                self.__updater.updateOnce()
        self.__isInPostmortem = True
        self.onPostMortemSwitched(noRespawnPossible, respawnAvailable)
        return

    def switchToOther(self, vehicleID):
        if vehicleID is None:
            self.notifyStateChanged(VEHICLE_VIEW_STATE.SWITCHING, 0)
            self.__needInvalidate = True
            return
        elif self.__vehicleID == vehicleID and not self.__needInvalidate:
            return
        else:
            self.__needInvalidate = False
            self.notifyStateChanged(VEHICLE_VIEW_STATE.SWITCHING, vehicleID)
            self.__waitingTI.stop()
            if self.__updater:
                self.__updater.stop()
            self.__vehicleID = vehicleID
            self.__isRqToSwitch = True
            self.notifyStateChanged(VEHICLE_VIEW_STATE.PLAYER_INFO, self.__vehicleID)
            self.__cachedStateValues.clear()
            self.__waitingTI.start()
            return

    def movingToRespawn(self):
        self.__isInPostmortem = False
        self.notifyStateChanged(VEHICLE_VIEW_STATE.SWITCHING, 0)
        self.onRespawnBaseMoving()
        self.__cachedStateValues.clear()

    def _waiting(self):
        vehicle = BigWorld.entity(self.__vehicleID)
        if vehicle is not None and vehicle.isStarted:
            self.__waitingTI.stop()
            self._setup(vehicle)
        return

    def _setup(self, vehicle):
        if self.__updater is not None:
            self.__updater = self.__updater.switch(self.__vehicleID)
        if self.__isRqToSwitch:
            nationID = vehicle.typeDescriptor.type.id[0]
            notifications = avatar_getter.getSoundNotifications()
            if notifications is not None:
                notifications.clear()
            SoundGroups.g_instance.soundModes.setCurrentNation(nations.NAMES[nationID])
        self.onVehicleControlling(vehicle)
        if self.__updater is not None:
            self.__updater.start()
        return
Example #17
0
class _VehicleUpdater(object):

    def __init__(self, vehCtrl, vehicleID):
        super(_VehicleUpdater, self).__init__()
        self.__isAlive = True
        self.__handlers = None
        self.__ctrl = weakref.proxy(vehCtrl)
        self.__vehicleID = vehicleID
        self.__updateTI = None
        self._setUpHandlers()
        return

    def handleStateChange(self, state, value):
        isStateHandled = False
        for handler in self.__handlers:
            isStateHandled |= handler.handleStateChange(state, value)

        return isStateHandled

    def switch(self, vehicleID):
        self.clear()
        self.__vehicleID = vehicleID
        self._setUpHandlers()
        return self

    def start(self):
        if self.__updateTI is None:
            self.__updateTI = TimeInterval(VEHICLE_UPDATE_INTERVAL, self, '_update')
        self.__updateTI.start()
        return

    def stop(self):
        if self.__updateTI is not None:
            self.__updateTI.stop()
            self.__updateTI = None
        return

    def clear(self):
        self.stop()
        if self.__handlers is not None:
            for handler in self.__handlers:
                handler.clear()

            self.__handlers = None
        self.__vehicleID = None
        self.__isAlive = True
        return

    def updateOnce(self):
        self._update()

    def notifyStateChanged(self, state, value):
        self.__ctrl.notifyStateChanged(state, value)

    def _update(self):
        states = []
        vehicle = BigWorld.entity(self.__vehicleID)
        if vehicle is not None and vehicle.isStarted:
            if not vehicle.isAlive() and self.__isAlive:
                self.__isAlive = False
                if vehicle.health > 0 and not vehicle.isCrewActive:
                    states.append((VEHICLE_VIEW_STATE.CREW_DEACTIVATED, 0))
                else:
                    states.append((VEHICLE_VIEW_STATE.DESTROYED, 0))
            for handler in self.__handlers:
                newStates = handler(vehicle)
                states.extend(newStates)

        for item in states:
            self.notifyStateChanged(*item)

        return

    def _setUpHandlers(self):
        vehicle = BigWorld.entity(self.__vehicleID)
        if vehicle is not None:
            isPlayerVehicle = vehicle.isPlayerVehicle
            if isPlayerVehicle:
                if not vehicle.isAlive():
                    self.__handlers = (_SpeedStateHandler(self, True),)
                else:
                    self.__handlers = (_SpeedStateHandler(self, True),)
            else:
                self.__handlers = (_HealthStateHandler(self), _SpeedStateHandler(self, False))
        return
class VehicleStateController(object):
    def __init__(self):
        super(VehicleStateController, self).__init__()
        self.__eManager = Event.EventManager()
        self.onVehicleStateUpdated = Event.Event(self.__eManager)
        self.onVehicleControlling = Event.Event(self.__eManager)
        self.onPostMortemSwitched = Event.Event(self.__eManager)
        self.onRespawnBaseMoving = Event.Event(self.__eManager)
        self.__waitingTI = TimeInterval(VEHICLE_WAINING_INTERVAL, self,
                                        '_waiting')
        self.__updateTI = TimeInterval(VEHICLE_UPDATE_INTERVAL, self,
                                       '_update')
        self.__vehicleID = 0
        self.__updater = _PlayerVehicleUpdater()
        self.__isRqToSwitch = False

    def clear(self):
        if self.__waitingTI:
            self.__waitingTI.stop()
            self.__waitingTI = None
        if self.__updateTI:
            self.__updateTI.stop()
            self.__updateTI = None
        self.__vehicleID = 0
        self.__isRqToSwitch = False
        self.__updater = None
        self.__eManager.clear()

    def setPlayerVehicle(self, vehicleID):
        self.onVehicleStateUpdated(VEHICLE_VIEW_STATE.PLAYER_INFO, vehicleID)
        self.__vehicleID = vehicleID
        self.__waitingTI.start()

    def getControllingVehicle(self):
        vehicle = None
        if self.__vehicleID:
            vehicle = BigWorld.entity(self.__vehicleID)
        return vehicle

    def invalidate(self, state, value):
        if state == VEHICLE_VIEW_STATE.DESTROYED:
            self.__updateTI.stop()
        self.onVehicleStateUpdated(state, value)

    def switchToPostmortem(self):
        self.__isRqToSwitch = False
        if avatar_getter.getPlayerVehicleID() == self.__vehicleID:
            self.__waitingTI.stop()
            self.__updateTI.stop()
        self.onPostMortemSwitched()

    def switchToAnother(self, vehicleID):
        if self.__vehicleID == vehicleID or vehicleID is None:
            return
        self.onVehicleStateUpdated(VEHICLE_VIEW_STATE.SWITCHING,
                                   self.__vehicleID)
        if self.__updater:
            self.__updater.clear()
        self.__waitingTI.stop()
        self.__updateTI.stop()
        self.__vehicleID = vehicleID
        self.__isRqToSwitch = True
        self.onVehicleStateUpdated(VEHICLE_VIEW_STATE.PLAYER_INFO,
                                   self.__vehicleID)
        self.__waitingTI.start()

    def movingToRespawn(self):
        self.onVehicleStateUpdated(VEHICLE_VIEW_STATE.SWITCHING, 0)
        self.onRespawnBaseMoving()

    def _waiting(self):
        vehicle = BigWorld.entity(self.__vehicleID)
        if vehicle is not None:
            self.__waitingTI.stop()
            self._setup(vehicle)

    def _update(self):
        states = self.__updater.update(self.__vehicleID, self.__updateTI)
        if states is not None:
            for item in states:
                self.onVehicleStateUpdated(*item)

    def _setup(self, vehicle):
        self.__updater = self.__updater.switch(vehicle.isPlayer)
        if self.__isRqToSwitch:
            nationID = vehicle.typeDescriptor.type.id[0]
            notifications = avatar_getter.getSoundNotifications()
            if notifications:
                notifications.clear()
            SoundGroups.g_instance.soundModes.setCurrentNation(
                nations.NAMES[nationID])
        self.onVehicleControlling(vehicle)
        if not vehicle.isAlive():
            self.onVehicleStateUpdated(VEHICLE_VIEW_STATE.DESTROYED, None)
        else:
            self.__updateTI.start()
Example #19
0
class VehicleStateController(IBattleController):
    """
    Class of controller that tracks specified vehicle on arena. At any time there is only one
    instance of this class. When player's own vehicle is destroyed, controller can track other
    vehicles on player's team.
    The main goal of the controller to combine all knowledge about vehicle state changes and to
    notify subscribers about that through appropriate events. The controller declares public
    interface to know about changes. Triggers call these method to notify the controller about
    specific changes that occur outside client. Also there is a list of changes that are triggered
    directly by the controller via the updater. The updater tracks those parameters on which there
    are no outside triggers or when required to control triggering frequency.
    """

    def __init__(self):
        """
        Constructor. Initializes internal variables.
        """
        super(VehicleStateController, self).__init__()
        self.__eManager = Event.EventManager()
        self.onVehicleStateUpdated = Event.Event(self.__eManager)
        self.onVehicleControlling = Event.Event(self.__eManager)
        self.onPostMortemSwitched = Event.Event(self.__eManager)
        self.onRespawnBaseMoving = Event.Event(self.__eManager)
        self.__cachedStateValues = {}
        self.__waitingTI = TimeInterval(VEHICLE_WAINING_INTERVAL, self, '_waiting')
        self.__vehicleID = 0
        self.__updater = None
        self.__isRqToSwitch = False
        self.__isInPostmortem = False
        return

    def getControllerID(self):
        return BATTLE_CTRL_ID.OBSERVED_VEHICLE_STATE

    def startControl(self):
        pass

    def stopControl(self):
        """
        Clears internal variables and stops timers.
        :return:
        """
        if self.__waitingTI is not None:
            self.__waitingTI.stop()
            self.__waitingTI = None
        if self.__updater is not None:
            self.__updater.clear()
            self.__updater = None
        self.__vehicleID = 0
        self.__isRqToSwitch = False
        self.__isInPostmortem = False
        self.__eManager.clear()
        self.__cachedStateValues.clear()
        return

    @property
    def isInPostmortem(self):
        return self.__isInPostmortem

    def setPlayerVehicle(self, vehicleID):
        """
        Sets ID of player's own vehicle.
        
        :param vehicleID: ID of vehicle entity
        """
        self.notifyStateChanged(VEHICLE_VIEW_STATE.PLAYER_INFO, vehicleID)
        self.__vehicleID = vehicleID
        self.__updater = _VehicleUpdater(self, self.__vehicleID)
        self.__waitingTI.start()

    def getControllingVehicle(self):
        """
        Gets entity of vehicle that is controlling.
        
        :return: entity of vehicle or None
        """
        vehicle = None
        if self.__vehicleID:
            vehicle = BigWorld.entity(self.__vehicleID)
        return vehicle

    def getControllingVehicleID(self):
        return self.__vehicleID

    def notifyStateChanged(self, stateID, value):
        """
        Store the specified state value, and raise the event
        :param stateID: id for state, listed within VEHICLE_VIEW_STATE
        :param value: state value
        """
        if stateID == VEHICLE_VIEW_STATE.DEVICES:
            self.__cachedStateValues.setdefault(stateID, [])
            self.__cachedStateValues[stateID].append(value)
        else:
            self.__cachedStateValues[stateID] = value
        self.onVehicleStateUpdated(stateID, value)

    def getStateValue(self, stateID):
        """
        Returns the last value for the the desired state
        :param stateID: id of state, listed within VEHICLE_VIEW_STATE
        :return: None or state value
        """
        if stateID in self.__cachedStateValues:
            return self.__cachedStateValues[stateID]
        else:
            return None

    def refreshVehicleStateValue(self, stateID):
        """
        Re-calls Update on the cached value of the vehicle state, nothing if not cached
        :param stateID: id of state, listed within VEHICLE_VIEW_STATE
        """
        if stateID in self.__cachedStateValues:
            self.onVehicleStateUpdated(stateID, self.__cachedStateValues[stateID])

    def invalidate(self, state, value, vehicleID = 0):
        """
        Invalidates vehicle sates. The method should be invoked by vehicle state change trigger.
        
        :param state: A state listed within VEHICLE_VIEW_STATE
        :param value: New state value
        :param vehicleID: ID of vehicle for which the given state is changed.
        """
        if vehicleID != 0 and vehicleID != self.__vehicleID:
            return
        else:
            isStateChangeHandled = False
            if self.__isRqToSwitch and self.__waitingTI.isStarted():
                self._waiting()
            if self.__updater is not None:
                isStateChangeHandled = self.__updater.handleStateChange(state, value)
            if not isStateChangeHandled:
                self.notifyStateChanged(state, value)
            return

    def switchToPostmortem(self, noRespawnPossible, respawnAvailable):
        """
        Switches to postmortem mode.
        :param leave:
        """
        self.__isRqToSwitch = False
        if avatar_getter.getPlayerVehicleID() == self.__vehicleID:
            if self.__updater is not None:
                self.__updater.stop()
                self.__updater.updateOnce()
        self.__isInPostmortem = True
        self.onPostMortemSwitched(noRespawnPossible, respawnAvailable)
        return

    def switchToOther(self, vehicleID):
        """
        Switches to another vehicle.
        
        :param vehicleID: ID of a new vehicle to be tracked.
        """
        if self.__vehicleID == vehicleID or vehicleID is None:
            return
        else:
            self.notifyStateChanged(VEHICLE_VIEW_STATE.SWITCHING, vehicleID)
            self.__waitingTI.stop()
            if self.__updater:
                self.__updater.stop()
            self.__vehicleID = vehicleID
            self.__isRqToSwitch = True
            self.notifyStateChanged(VEHICLE_VIEW_STATE.PLAYER_INFO, self.__vehicleID)
            self.__cachedStateValues.clear()
            self.__waitingTI.start()
            return

    def movingToRespawn(self):
        """
        Emits the appropriate event and state change event. The method should be called
        when the vehicle is moved to respawn.
        :return:
        """
        self.__isInPostmortem = False
        self.notifyStateChanged(VEHICLE_VIEW_STATE.SWITCHING, 0)
        self.onRespawnBaseMoving()
        self.__cachedStateValues.clear()

    def _waiting(self):
        """
        Callback to be invoked when the waiting timer is elapsed. Starts the updater when the
        avatar has been switched to the required vehicle.
        """
        vehicle = BigWorld.entity(self.__vehicleID)
        if vehicle is not None and vehicle.isStarted:
            self.__waitingTI.stop()
            self._setup(vehicle)
        return

    def _setup(self, vehicle):
        """
        Set up the updater and other properties
        :param vehicle: Vehicle entity.
        """
        if self.__updater is not None:
            self.__updater = self.__updater.switch(self.__vehicleID)
        if self.__isRqToSwitch:
            nationID = vehicle.typeDescriptor.type.id[0]
            notifications = avatar_getter.getSoundNotifications()
            if notifications is not None:
                notifications.clear()
            SoundGroups.g_instance.soundModes.setCurrentNation(nations.NAMES[nationID])
        self.onVehicleControlling(vehicle)
        if self.__updater is not None:
            self.__updater.start()
        return
Example #20
0
class _VehicleUpdater(object):
    """
    The class implements logic for tracking changes of vehicle parameters in equal time intervals.
    It encapsulates different algorithms of tracking based on vehicle type. The inner logic is
    based on the custom state handlers (classes derived from _StateHandler).
    """

    def __init__(self, vehCtrl, vehicleID):
        """
        Constructor. Initializes internal variables.
        
        :param vehCtrl: Reference to vehicle state controller owning this updater.
        :param vehicleID: Unique identifier of vehicle to be tracked
        """
        super(_VehicleUpdater, self).__init__()
        self.__isAlive = True
        self.__handlers = None
        self.__ctrl = weakref.proxy(vehCtrl)
        self.__vehicleID = vehicleID
        self.__updateTI = None
        self._setUpHandlers()
        return

    def handleStateChange(self, state, value):
        """
        Represents a hook to catch states changes before the vehicle state controller propagates
        them to subscribers. Redirects the call to each handler to perform required logic.
        
        :param state: A state listed within VEHICLE_VIEW_STATE
        :param value: State value
        :return: True if any handler returns True. Otherwise - False.
        """
        isStateHandled = False
        for handler in self.__handlers:
            isStateHandled |= handler.handleStateChange(state, value)

        return isStateHandled

    def switch(self, vehicleID):
        """
        Switches the updater to another vehicle: reset internal states and handlers.
        
        :param vehicleID: Unique identifier of a new vehicle that will be tracked
        """
        self.clear()
        self.__vehicleID = vehicleID
        self._setUpHandlers()
        return self

    def start(self):
        """
        Sets up and starts the timer to invalidate handlers.
        """
        if self.__updateTI is None:
            self.__updateTI = TimeInterval(VEHICLE_UPDATE_INTERVAL, self, '_update')
        self.__updateTI.start()
        return

    def stop(self):
        """
        Stops and clears running timer (if any).
        """
        if self.__updateTI is not None:
            self.__updateTI.stop()
            self.__updateTI = None
        return

    def clear(self):
        """
        Clears internal variables and stops timer.
        """
        self.stop()
        if self.__handlers is not None:
            for handler in self.__handlers:
                handler.clear()

            self.__handlers = None
        self.__vehicleID = None
        self.__isAlive = True
        return

    def updateOnce(self):
        """
        Invokes this routine to singe update of information about vehicle if it is needed.
        For example, player's vehicle is destroyed, we need to update modules and crew states, set max speed.
        """
        raise self.__updateTI is None or not self.__updateTI.isStarted() or AssertionError('Updater is started')
        self._update()
        return

    def notifyStateChanged(self, state, value):
        """
        The helper method to provide handler ability to notify subscribers about changes of
        vehicle's states through the vehicle state controller.
        
        :param state: A state listed within VEHICLE_VIEW_STATE
        :param value: State value.
        """
        self.__ctrl.notifyStateChanged(state, value)

    def _update(self):
        """
        Callback on timer tick event. Initiates invalidation of all handlers, get all states
        changes and redirects them to the vehicle state controller by emitting appropriate events.
        """
        states = []
        vehicle = BigWorld.entity(self.__vehicleID)
        if vehicle is not None and vehicle.isStarted:
            if not vehicle.isAlive() and self.__isAlive:
                self.__isAlive = False
                if vehicle.health > 0 and not vehicle.isCrewActive:
                    states.append((VEHICLE_VIEW_STATE.CREW_DEACTIVATED, 0))
                else:
                    states.append((VEHICLE_VIEW_STATE.DESTROYED, 0))
            for handler in self.__handlers:
                newStates = handler(vehicle)
                states.extend(newStates)

        for item in states:
            self.notifyStateChanged(*item)

        return

    def _setUpHandlers(self):
        """
        Determines a list of handlers based on vehicle type and sets up them.
        """
        vehicle = BigWorld.entity(self.__vehicleID)
        if vehicle is not None:
            isPlayerVehicle = vehicle.isPlayerVehicle
            if isPlayerVehicle:
                if not vehicle.isAlive():
                    self.__handlers = (_SpeedStateHandler(self, True),)
                else:
                    self.__handlers = (_SpeedStateHandler(self, True), _RpmStateHandler(self, vehicle), _EngineStateHandler(self, vehicle))
            else:
                self.__handlers = (_HealthStateHandler(self),
                 _SpeedStateHandler(self, False),
                 _RpmStateHandler(self, vehicle),
                 _EngineStateHandler(self, vehicle))
        return
class VehicleStateController(IBattleController):
    """
    Class of controller that tracks specified vehicle on arena. At any time there is only one
    instance of this class. When player's own vehicle is destroyed, controller can track other
    vehicles on player's team.
    The main goal of the controller to combine all knowledge about vehicle state changes and to
    notify subscribers about that through appropriate events. The controller declares public
    interface to know about changes. Triggers call these method to notify the controller about
    specific changes that occur outside client. Also there is a list of changes that are triggered
    directly by the controller via the updater. The updater tracks those parameters on which there
    are no outside triggers or when required to control triggering frequency.
    """

    def __init__(self):
        """
        Constructor. Initializes internal variables.
        """
        super(VehicleStateController, self).__init__()
        self.__eManager = Event.EventManager()
        self.onVehicleStateUpdated = Event.Event(self.__eManager)
        self.onVehicleControlling = Event.Event(self.__eManager)
        self.onPostMortemSwitched = Event.Event(self.__eManager)
        self.onRespawnBaseMoving = Event.Event(self.__eManager)
        self.__cachedStateValues = {}
        self.__waitingTI = TimeInterval(VEHICLE_WAINING_INTERVAL, self, '_waiting')
        self.__vehicleID = 0
        self.__updater = None
        self.__isRqToSwitch = False
        self.__isInPostmortem = False
        return

    def getControllerID(self):
        return BATTLE_CTRL_ID.OBSERVED_VEHICLE_STATE

    def startControl(self):
        pass

    def stopControl(self):
        """
        Clears internal variables and stops timers.
        :return:
        """
        if self.__waitingTI is not None:
            self.__waitingTI.stop()
            self.__waitingTI = None
        if self.__updater is not None:
            self.__updater.clear()
            self.__updater = None
        self.__vehicleID = 0
        self.__isRqToSwitch = False
        self.__isInPostmortem = False
        self.__eManager.clear()
        self.__cachedStateValues.clear()
        return

    @property
    def isInPostmortem(self):
        return self.__isInPostmortem

    def setPlayerVehicle(self, vehicleID):
        """
        Sets ID of player's own vehicle.
        
        :param vehicleID: ID of vehicle entity
        """
        self.notifyStateChanged(VEHICLE_VIEW_STATE.PLAYER_INFO, vehicleID)
        self.__vehicleID = vehicleID
        self.__updater = _VehicleUpdater(self, self.__vehicleID)
        self.__waitingTI.start()

    def getControllingVehicle(self):
        """
        Gets entity of vehicle that is controlling.
        
        :return: entity of vehicle or None
        """
        vehicle = None
        if self.__vehicleID:
            vehicle = BigWorld.entity(self.__vehicleID)
        return vehicle

    def notifyStateChanged(self, stateID, value):
        """
        Store the specified state value, and raise the event
        :param stateID: id for state, listed within VEHICLE_VIEW_STATE
        :param value: state value
        """
        self.__cachedStateValues[stateID] = value
        self.onVehicleStateUpdated(stateID, value)

    def getStateValue(self, stateID):
        """
        Returns the last value for the the desired state
        :param stateID: id of state, listed within VEHICLE_VIEW_STATE
        :return: None or state value
        """
        if stateID in self.__cachedStateValues:
            return self.__cachedStateValues[stateID]
        else:
            return None
            return None

    def invalidate(self, state, value, vehicleID = 0):
        """
        Invalidates vehicle sates. The method should be invoked by vehicle state change trigger.
        
        :param state: A state listed within VEHICLE_VIEW_STATE
        :param value: New state value
        :param vehicleID: ID of vehicle for which the given state is changed.
        """
        if vehicleID != 0 and vehicleID != self.__vehicleID:
            return
        else:
            isStateChangeHandled = False
            if self.__updater is not None:
                isStateChangeHandled = self.__updater.handleStateChange(state, value)
            if not isStateChangeHandled:
                self.notifyStateChanged(state, value)
            return

    def switchToPostmortem(self):
        """
        Switches to postmortem mode.
        """
        self.__isRqToSwitch = False
        if avatar_getter.getPlayerVehicleID() == self.__vehicleID:
            self.__waitingTI.stop()
            if self.__updater is not None:
                self.__updater.stop()
        self.__isInPostmortem = True
        self.onPostMortemSwitched()
        return

    def switchToOther(self, vehicleID):
        """
        Switches to another vehicle.
        
        :param vehicleID: ID of a new vehicle to be tracked.
        """
        if self.__vehicleID == vehicleID or vehicleID is None:
            return
        else:
            self.notifyStateChanged(VEHICLE_VIEW_STATE.SWITCHING, vehicleID)
            self.__waitingTI.stop()
            if self.__updater:
                self.__updater.stop()
            self.__vehicleID = vehicleID
            self.__isRqToSwitch = True
            self.notifyStateChanged(VEHICLE_VIEW_STATE.PLAYER_INFO, self.__vehicleID)
            self.__waitingTI.start()
            return

    def movingToRespawn(self):
        """
        Emits the appropriate event and state change event. The method should be called
        when the vehicle is moved to respawn.
        :return:
        """
        self.notifyStateChanged(VEHICLE_VIEW_STATE.SWITCHING, 0)
        self.onRespawnBaseMoving()

    def _waiting(self):
        """
        Callback to be invoked when the waiting timer is elapsed. Starts the updater when the
        avatar has been switched to the required vehicle.
        """
        vehicle = BigWorld.entity(self.__vehicleID)
        if vehicle is not None:
            self.__waitingTI.stop()
            self._setup(vehicle)
        return

    def _setup(self, vehicle):
        """
        Set up the updater and other properties
        :param vehicle: Vehicle entity.
        """
        if self.__updater is not None:
            self.__updater = self.__updater.switch(self.__vehicleID)
        if self.__isRqToSwitch:
            nationID = vehicle.typeDescriptor.type.id[0]
            notifications = avatar_getter.getSoundNotifications()
            if notifications is not None:
                notifications.clear()
            SoundGroups.g_instance.soundModes.setCurrentNation(nations.NAMES[nationID])
        self.onVehicleControlling(vehicle)
        if not vehicle.isAlive():
            self.notifyStateChanged(VEHICLE_VIEW_STATE.DESTROYED, None)
        elif self.__updater is not None:
            self.__updater.start()
        return
Example #22
0
class DebugController(IViewComponentsController):
    """Controller for the debug panel.
    
    This class starts internal update cycle and updates debug panel.
    In order to collect lagging info from near vehicles, these vehicle's ids
    should be provided from outside using special methods.
    """
    def __init__(self):
        super(DebugController, self).__init__()
        self._debugPanelUI = None
        self._timeInterval = None
        self._visibleVehicles = set()
        return

    def getControllerID(self):
        return BATTLE_CTRL_ID.DEBUG

    def startControl(self):
        self._timeInterval = TimeInterval(_UPDATE_INTERVAL, self, '_update')
        self._timeInterval.start()

    def stopControl(self):
        self._timeInterval.stop()
        self._timeInterval = None
        self._debugPanelUI = None
        self._visibleVehicles = set()
        return

    def setViewComponents(self, debugPanelUI):
        raise isinstance(debugPanelUI, IDebugPanel) or AssertionError
        self._debugPanelUI = debugPanelUI

    def clearViewComponents(self):
        self._debugPanelUI = None
        return

    def startVehicleVisual(self, vehicleID):
        if avatar_getter.getPlayerVehicleID() != vehicleID:
            self._visibleVehicles.add(vehicleID)

    def stopVehicleVisual(self, vehicleID):
        self._visibleVehicles.discard(vehicleID)

    def _update(self):
        replayCtrl = BattleReplay.g_replayCtrl
        if replayCtrl.isPlaying and replayCtrl.fps > 0:
            fps = BigWorld.getFPS()[1]
            fpsReplay = int(replayCtrl.fps)
            ping = replayCtrl.ping
            isLaggingNow = replayCtrl.isLaggingNow
        else:
            fpsReplay = -1
            player = BigWorld.player()
            isLaggingNow = player.filter.isLaggingNow if player is not None else False
            if not isLaggingNow:
                for vehicleID in self._visibleVehicles:
                    vehicle = BigWorld.entities[vehicleID]
                    if vehicle is not None and vehicle.isAlive():
                        try:
                            if vehicle.filter.isLagginNow:
                                isLaggingNow = True
                                break
                        except AttributeError:
                            pass

            avgLatency = BigWorld.LatencyInfo().value[3]
            if avgLatency:
                ping = min(avgLatency * 1000, 999)
                if ping < 999:
                    ping = max(1, ping - 500.0 * constants.SERVER_TICK_LENGTH)
            else:
                ping = 999
            fpsInfo = BigWorld.getFPS()
            g_statistics.update(fpsInfo, ping, isLaggingNow)
            fps = fpsInfo[1]
            if replayCtrl.isRecording:
                replayCtrl.setFpsPingLag(fps, ping, isLaggingNow)
        if self._debugPanelUI is not None:
            self._debugPanelUI.updateDebugInfo(int(ping),
                                               int(fps),
                                               isLaggingNow,
                                               fpsReplay=fpsReplay)
        return
class VehicleStateController(IBattleController):

    def __init__(self):
        super(VehicleStateController, self).__init__()
        self.__eManager = Event.EventManager()
        self.onVehicleStateUpdated = Event.Event(self.__eManager)
        self.onVehicleControlling = Event.Event(self.__eManager)
        self.onPostMortemSwitched = Event.Event(self.__eManager)
        self.onRespawnBaseMoving = Event.Event(self.__eManager)
        self.onEquipmentComponentUpdated = Event.ContextEvent(self.__eManager)
        self.__cachedStateValues = {}
        self.__cachedRepairingCallbackID = None
        self.__waitingTI = TimeInterval(VEHICLE_WAINING_INTERVAL, self, '_waiting')
        self.__vehicleID = 0
        self.__updater = None
        self.__isRqToSwitch = False
        self.__isInPostmortem = False
        self.__needInvalidate = False
        return

    def getControllerID(self):
        return BATTLE_CTRL_ID.OBSERVED_VEHICLE_STATE

    def startControl(self, *_):
        pass

    def stopControl(self):
        if self.__waitingTI is not None:
            self.__waitingTI.stop()
            self.__waitingTI = None
        if self.__updater is not None:
            self.__updater.clear()
            self.__updater = None
        self.__vehicleID = 0
        self.__isRqToSwitch = False
        self.__isInPostmortem = False
        self.__eManager.clear()
        self.__cachedStateValues.clear()
        if self.__cachedRepairingCallbackID:
            BigWorld.cancelCallback(self.__cachedRepairingCallbackID)
        return

    @property
    def isInPostmortem(self):
        return self.__isInPostmortem

    def setPlayerVehicle(self, vehicleID):
        self.notifyStateChanged(VEHICLE_VIEW_STATE.PLAYER_INFO, vehicleID)
        self.__vehicleID = vehicleID
        self.__updater = _VehicleUpdater(self, self.__vehicleID)
        self.__waitingTI.restart()

    def getControllingVehicle(self):
        vehicle = None
        if self.__vehicleID:
            vehicle = BigWorld.entity(self.__vehicleID)
        return vehicle

    def getControllingVehicleID(self):
        return self.__vehicleID

    def notifyStateChanged(self, stateID, value):
        if stateID == VEHICLE_VIEW_STATE.DEVICES:
            self.__cachedStateValues.setdefault(stateID, {})
            deviceName = value[0]
            cachedRepairingDeviceName = first(self.__cachedStateValues.get(VEHICLE_VIEW_STATE.REPAIRING, ()))
            if cachedRepairingDeviceName == deviceName and value[2] == DEVICE_STATE_NORMAL:
                self.__cachedStateValues.pop(VEHICLE_VIEW_STATE.REPAIRING)
            self.__cachedStateValues[stateID][deviceName] = value
        else:
            if stateID == VEHICLE_VIEW_STATE.REPAIRING:
                if self.__cachedRepairingCallbackID:
                    BigWorld.cancelCallback(self.__cachedRepairingCallbackID)
                BigWorld.callback(value[2], partial(self.__cachedRepairingCallback, value))
            self.__cachedStateValues[stateID] = value
        self.onVehicleStateUpdated(stateID, value)

    def __cachedRepairingCallback(self, value):
        self.__cachedRepairingCallbackID = None
        if self.__cachedStateValues.get(VEHICLE_VIEW_STATE.REPAIRING) == value:
            self.__cachedStateValues.pop(VEHICLE_VIEW_STATE.REPAIRING)
        return

    def getStateValue(self, stateID):
        if stateID in self.__cachedStateValues:
            if stateID == VEHICLE_VIEW_STATE.DEVICES:
                value = self.__cachedStateValues[stateID].values()
            else:
                value = self.__cachedStateValues[stateID]
            return value
        else:
            return None

    def refreshVehicleStateValue(self, stateID):
        if stateID in self.__cachedStateValues:
            self.onVehicleStateUpdated(stateID, self.__cachedStateValues[stateID])

    def invalidate(self, state, value, vehicleID=0):
        if vehicleID != 0 and vehicleID != self.__vehicleID:
            return
        else:
            isStateChangeHandled = False
            if self.__isRqToSwitch and self.__waitingTI.isStarted():
                self._waiting()
            if self.__updater is not None:
                isStateChangeHandled = self.__updater.handleStateChange(state, value)
            if not isStateChangeHandled:
                self.notifyStateChanged(state, value)
            return

    def switchToPostmortem(self, noRespawnPossible, respawnAvailable):
        self.__isRqToSwitch = False
        if avatar_getter.getPlayerVehicleID() == self.__vehicleID:
            if self.__updater is not None:
                self.__updater.stop()
                self.__updater.updateOnce()
        self.__isInPostmortem = True
        self.onPostMortemSwitched(noRespawnPossible, respawnAvailable)
        return

    def switchToOther(self, vehicleID):
        if vehicleID is None:
            self.notifyStateChanged(VEHICLE_VIEW_STATE.SWITCHING, 0)
            self.__needInvalidate = True
            return
        elif self.__vehicleID == vehicleID and not self.__needInvalidate:
            return
        else:
            self.__needInvalidate = False
            self.notifyStateChanged(VEHICLE_VIEW_STATE.SWITCHING, vehicleID)
            self.__waitingTI.stop()
            if self.__updater:
                self.__updater.stop()
            self.__vehicleID = vehicleID
            self.__isRqToSwitch = True
            self.notifyStateChanged(VEHICLE_VIEW_STATE.PLAYER_INFO, self.__vehicleID)
            self.__cachedStateValues.clear()
            self.__waitingTI.start()
            return

    def refreshObserverVehicleVisual(self):
        vehicle = self.getControllingVehicle()
        if vehicle is not None:
            self.onVehicleControlling(vehicle)
        return

    def movingToRespawn(self):
        self.__isInPostmortem = False
        self.notifyStateChanged(VEHICLE_VIEW_STATE.SWITCHING, 0)
        self.onRespawnBaseMoving()
        self.__cachedStateValues.clear()

    def _waiting(self):
        vehicle = BigWorld.entity(self.__vehicleID)
        if vehicle is not None and vehicle.isStarted:
            self.__waitingTI.stop()
            self._setup(vehicle)
        return

    def _setup(self, vehicle):
        if self.__updater is not None:
            self.__updater = self.__updater.switch(self.__vehicleID)
        if self.__isRqToSwitch:
            nationID = vehicle.typeDescriptor.type.id[0]
            notifications = avatar_getter.getSoundNotifications()
            if notifications is not None:
                notifications.clear()
            SoundGroups.g_instance.soundModes.setCurrentNation(nations.NAMES[nationID])
        self.onVehicleControlling(vehicle)
        if VEHICLE_VIEW_STATE.DUAL_GUN_STATE_UPDATED in self.__cachedStateValues.keys():
            self.onVehicleStateUpdated(VEHICLE_VIEW_STATE.DUAL_GUN_STATE_UPDATED, self.getStateValue(VEHICLE_VIEW_STATE.DUAL_GUN_STATE_UPDATED))
        if self.__updater is not None:
            self.__updater.start()
        return
Example #24
0
class IndicatorManager(object):
    def __init__(self, config):
        self.__config = config
        self.__panels = []
        self.__isSetHandler = False
        self.__visible = False
        self.__crosshairPosition = [0, 0]
        self.__onShoot = None
        self.__onShot = None
        self.__onShotResult = None
        self.__intervalHandlers = Event()
        self.__eventHandlers = Event()
        self.__keyHandlers = {}
        interval = config['common']['updateInterval']
        self.__timeInterval = TimeInterval(interval, self, 'onWatchStats')
        g_eventBus.addListener(events.AppLifeCycleEvent.INITIALIZED,
                               self.onAppInitialized)
        g_eventBus.addListener(events.AppLifeCycleEvent.DESTROYED,
                               self.onAppDestroyed)
        appLoader = dependency.instance(IAppLoader)
        appLoader.onGUISpaceEntered += self.onGUISpaceEntered
        appLoader.onGUISpaceLeft += self.onGUISpaceLeft
        g_statsCollector.eventHandlers.clear()

    def initPanel(self):
        _logger.info('initPanel')
        self.addHandler()
        g_statsCollector.eventHandlers += self.onEvent
        g_statsCollector.start()
        g_statsCollector.updateArenaInfo()
        clientStatus = g_statsCollector.clientStatus
        self.__panels = []
        self.__keyHandlers = {}
        for paneldef in self.__config.get('panelDefs', []):
            if paneldef['channel'] == 'indicator':
                panel = StatsIndicator(paneldef, clientStatus)
                if 'events' in paneldef:
                    self.__eventHandlers += panel.onEvent
                else:
                    self.__intervalHandlers += panel.update
                if 'toggleKey' in paneldef['style']:
                    keyName = paneldef['style']['toggleKey']
                    keyId = getattr(Keys, keyName)
                    if keyId not in self.__keyHandlers:
                        self.__keyHandlers[keyId] = Event()
                    self.__keyHandlers[keyId] += panel.toggle
            elif paneldef['channel'] == 'status':
                panel = StatsLogger(paneldef, clientStatus)
                self.__intervalHandlers += panel.update
            elif paneldef['channel'] == 'event':
                panel = EventLogger(paneldef, clientStatus)
                self.__eventHandlers += panel.onEvent
            self.__panels.append(panel)
        session = dependency.instance(IBattleSessionProvider)
        ctrl = session.shared.crosshair
        self.changeView(ctrl.getViewID())
        self.updateScreenPosition()
        self.updateCrosshairPosition()

    def finiPanel(self):
        _logger.info('finiPanel')
        self.stopIntervalTimer()
        self.invisiblePanel()
        self.removeHandler()
        for panel in self.__panels:
            if isinstance(panel, EventLogger):
                _logger.info('del EventLogger.onEvent')
                g_statsCollector.eventHandlers -= panel.onEvent
        self.__panels = []
        self.__keyHandlers = {}

    def addHandler(self):
        if self.__isSetHandler:
            return
        self.__isSetHandler = True
        arena = BigWorld.player().arena
        arena.onPeriodChange += self.onArenaPeriodChange
        session = dependency.instance(IBattleSessionProvider)
        ctl = session.shared.vehicleState
        ctl.onVehicleStateUpdated += self.onVehicleStateUpdated
        ctl = session.shared.crosshair
        ctl.onCrosshairViewChanged += self.onCrosshairViewChanged
        ctl.onCrosshairPositionChanged += self.onCrosshairPositionChanged
        self.__crosshairPosition = list(ctl.getScaledPosition())
        g_guiResetters.add(self.onScreenResolutionChanged)
        g_keyEventHandlers.add(self.__handleKeyEvent)

    def removeHandler(self):
        if not self.__isSetHandler:
            return
        self.__isSetHandler = False
        player = BigWorld.player()
        if player:
            arena = player.arena
            if arena:
                arena.onPeriodChange -= self.onArenaPeriodChange
        session = dependency.instance(IBattleSessionProvider)
        ctl = session.shared.vehicleState
        if ctl:
            ctl.onVehicleStateUpdated -= self.onVehicleStateUpdated
        ctl = session.shared.crosshair
        if ctl:
            ctl.onCrosshairViewChanged -= self.onCrosshairViewChanged
            ctl.onCrosshairPositionChanged -= self.onCrosshairPositionChanged
        g_guiResetters.remove(self.onScreenResolutionChanged)
        g_keyEventHandlers.remove(self.__handleKeyEvent)

    def visiblePanel(self):
        if self.__visible:
            return
        self.__visible = True
        _logger.info('panel.start')
        for panel in self.__panels:
            panel.start()

    def invisiblePanel(self):
        if not self.__visible:
            return
        self.__visible = False
        _logger.info('panel.stop')
        for panel in self.__panels:
            panel.stop()

    def startIntervalTimer(self):
        if not self.__timeInterval.isStarted():
            _logger.info('TimeInterval: start')
            self.__timeInterval.start()

    def stopIntervalTimer(self):
        if self.__timeInterval.isStarted():
            _logger.info('TimeInterval: stop')
            self.__timeInterval.stop()

    def changeView(self, viewID):
        _logger.debug('changeView: %s', CROSSHAIR_VIEW_SYMBOL[viewID])
        for panel in self.__panels:
            panel.changeView(viewID)

    def updateScreenPosition(self):
        width, height = GUI.screenResolution()
        _logger.debug('updateScreenPosition: (%d, %d)', width, height)
        for panel in self.__panels:
            panel.updateScreenPosition(width, height)

    def updateCrosshairPosition(self):
        x, y = self.__crosshairPosition
        _logger.debug('updateCrosshairPosition: (%d, %d)', x, y)
        for panel in self.__panels:
            _logger.debug('updateCrosshairPosition: call panel: "%s"',
                          panel.name)
            panel.updateCrosshairPosition(x, y)

    def onAppInitialized(self, event):
        if event.ns != APP_NAME_SPACE.SF_BATTLE:
            return
        _logger.info('AppLifeCycleEvent.INITIALIZED: SF_BATTLE')
        #self.initPanel()

    def onAppDestroyed(self, event):
        if event.ns != APP_NAME_SPACE.SF_BATTLE:
            return
        _logger.info('AppLifeCycleEvent.DESTROYED: SF_BATTLE')
        self.finiPanel()

    def onGUISpaceEntered(self, spaceID):
        if spaceID != GuiGlobalSpaceID.BATTLE:
            return
        _logger.info('onGUISpaceEnterd: %s', GUI_GLOBAL_SPACE_SYMBOL[spaceID])
        self.initPanel()

    def onGUISpaceLeft(self, spaceID):
        if spaceID != GuiGlobalSpaceID.BATTLE:
            return
        _logger.info('onGUISpaceLeft: %s', GUI_GLOBAL_SPACE_SYMBOL[spaceID])
        self.finiPanel()

    def onArenaPeriodChange(self, period, periodEndTime, periodLength,
                            periodAdditionalInfo):
        _logger.info('onArenaPeriodChange: %s', ARENA_PERIOD_SYMBOL[period])
        if period == ARENA_PERIOD.PREBATTLE:
            self.visiblePanel()
        elif period == ARENA_PERIOD.BATTLE:
            self.visiblePanel()
            self.startIntervalTimer()
        elif period == ARENA_PERIOD.AFTERBATTLE:
            self.stopIntervalTimer()
            self.invisiblePanel()

    def onVehicleStateUpdated(self, stateID, value):
        if stateID == VEHICLE_VIEW_STATE.DESTROYED:
            _logger.info('onVehicleStateUpdated: VEHICLE_VIEW_STATE.DESTROYED')
            self.stopIntervalTimer()
            self.invisiblePanel()

    def onScreenResolutionChanged(self):
        width, height = GUI.screenResolution()
        _logger.debug('onScreenResolutionChanged: (%d, %d)', width, height)
        for panel in self.__panels:
            panel.updateScreenPosition(width, height)

    def onCrosshairViewChanged(self, viewID):
        _logger.debug('crosshairViewChanged: %s',
                      CROSSHAIR_VIEW_SYMBOL[viewID])
        self.changeView(viewID)

    def onCrosshairPositionChanged(self, x, y):
        _logger.debug('onCrosshairPositionChanged: (%d, %d)', x, y)
        self.__crosshairPosition = [x, y]
        for panel in self.__panels:
            panel.updateCrosshairPosition(x, y)

    def onWatchStats(self):
        BigWorld.callback(0, partial(self.__intervalHandlers))

    def onEvent(self, reason):
        BigWorld.callback(0, partial(self.__eventHandlers, reason))

    def __handleKeyEvent(self, event):
        if event.isKeyDown() and not event.isRepeatedEvent():
            handlers = self.__keyHandlers.get(event.key, None)
            if handlers is not None:
                handlers()
                return True
        return False
class _EngineStateHandler(_StateHandler):
    """
    The class provides logic to track engine state changes and vehicle movement changes.
    All logic is based on changes of the current gear.
    """
    __slots__ = ('__weakref__', '__gear', '__vehMoveAnimTimer', '__engineStartAnimTimer')

    def __init__(self, updater, vehicle):
        """
        Constructor. Initializes internal variables based on vehicle state.
        
        :param updater: An instance of _VehicleUpdater class, that creates this handler.
        :param vehicle: Vehicle to be tracked.
        :return:
        """
        super(_EngineStateHandler, self).__init__(updater)
        self.__gear = vehicle.appearance.gear if vehicle is not None else _STOPPED_ENGINE_GEAR
        self.__vehMoveAnimTimer = TimeInterval(_VEHICLE_ANIM_DURATION, self, '_stopVehMoveAnim')
        self.__engineStartAnimTimer = TimeInterval(_VEHICLE_ANIM_DURATION, self, '_stopEngineStartAnim')
        return

    def clear(self):
        """
        Resets internal variables.
        """
        self.__gear = _STOPPED_ENGINE_GEAR
        self._stopVehMoveAnim()
        self._stopEngineStartAnim()

    def _invalidate(self, vehicle):
        """
        The method determines whether one of the following events has occurred and exposes the
        appropriate state change to the updater:
            1. Vehicle starts moving.
            2. Engine is started.
        By these events, appropriate animations are run on UI. To stop animations appropriate state
        change event is sent in _VEHICLE_ANIM_DURATION time. Note that animation duration depends
        on sound effect (track length). But right now there is no way to determine effect duration.
        Therefore for all vehicles the same constant is used.
        
        :param vehicle: A reference to the tracked vehicle(BW entity).
        :return: The state change if any. Otherwise an empty list.
        """
        states = []
        gear = vehicle.appearance.gear
        if self.__gear != gear:
            if not self.__gear and gear > 0:
                if not self.__vehMoveAnimTimer.isStarted():
                    states.append((VEHICLE_VIEW_STATE.VEHICLE_MOVEMENT_STATE, True))
                    self.__vehMoveAnimTimer.start()
            elif self.__gear == _STOPPED_ENGINE_GEAR and gear >= 0:
                if not self.__engineStartAnimTimer.isStarted():
                    states.append((VEHICLE_VIEW_STATE.VEHICLE_ENGINE_STATE, True))
                    self.__engineStartAnimTimer.start()
            elif self.__gear > 0 and not self.__gear:
                pass
            elif self.__gear >= 0 and gear == _STOPPED_ENGINE_GEAR:
                pass
            self.__gear = gear
        return states

    def _stopVehMoveAnim(self):
        """
        Stops 'vehicle start' animation by sending the appropriate event.
        """
        if self.__vehMoveAnimTimer.isStarted():
            self.__vehMoveAnimTimer.stop()
            self.notifyStateChanged(VEHICLE_VIEW_STATE.VEHICLE_MOVEMENT_STATE, False)

    def _stopEngineStartAnim(self):
        """
        Stops 'engine start' animation by sending the appropriate event.
        """
        if self.__engineStartAnimTimer.isStarted():
            self.__engineStartAnimTimer.stop()
            self.notifyStateChanged(VEHICLE_VIEW_STATE.VEHICLE_ENGINE_STATE, False)
class VehicleStateController(object):

    def __init__(self):
        super(VehicleStateController, self).__init__()
        self.__eManager = Event.EventManager()
        self.onVehicleStateUpdated = Event.Event(self.__eManager)
        self.onVehicleControlling = Event.Event(self.__eManager)
        self.onPostMortemSwitched = Event.Event(self.__eManager)
        self.onRespawnBaseMoving = Event.Event(self.__eManager)
        self.__waitingTI = TimeInterval(VEHICLE_WAINING_INTERVAL, self, '_waiting')
        self.__updateTI = TimeInterval(VEHICLE_UPDATE_INTERVAL, self, '_update')
        self.__vehicleID = 0
        self.__updater = _PlayerVehicleUpdater()
        self.__isRqToSwitch = False

    def clear(self):
        if self.__waitingTI:
            self.__waitingTI.stop()
            self.__waitingTI = None
        if self.__updateTI:
            self.__updateTI.stop()
            self.__updateTI = None
        self.__vehicleID = 0
        self.__isRqToSwitch = False
        self.__updater = None
        self.__eManager.clear()
        return

    def setPlayerVehicle(self, vehicleID):
        self.onVehicleStateUpdated(VEHICLE_VIEW_STATE.PLAYER_INFO, vehicleID)
        self.__vehicleID = vehicleID
        self.__waitingTI.start()

    def getControllingVehicle(self):
        vehicle = None
        if self.__vehicleID:
            vehicle = BigWorld.entity(self.__vehicleID)
        return vehicle

    def invalidate(self, state, value):
        if state == VEHICLE_VIEW_STATE.DESTROYED:
            self.__updateTI.stop()
        self.onVehicleStateUpdated(state, value)

    def switchToPostmortem(self):
        self.__isRqToSwitch = False
        if avatar_getter.getPlayerVehicleID() == self.__vehicleID:
            self.__waitingTI.stop()
            self.__updateTI.stop()
        self.onPostMortemSwitched()

    def switchToAnother(self, vehicleID):
        if self.__vehicleID == vehicleID or vehicleID is None:
            return
        else:
            if self.__updater:
                self.__updater.clear()
            self.__waitingTI.stop()
            self.__updateTI.stop()
            self.__vehicleID = vehicleID
            self.__isRqToSwitch = True
            self.onVehicleStateUpdated(VEHICLE_VIEW_STATE.PLAYER_INFO, self.__vehicleID)
            self.__waitingTI.start()
            return

    def _waiting(self):
        vehicle = BigWorld.entity(self.__vehicleID)
        if vehicle is not None:
            self.__waitingTI.stop()
            self._setup(vehicle)
        return

    def _update(self):
        states = self.__updater.update(self.__vehicleID, self.__updateTI)
        if states is not None:
            for item in states:
                self.onVehicleStateUpdated(*item)

        return

    def _setup(self, vehicle):
        self.__updater = self.__updater.switch(vehicle.isPlayer)
        if self.__isRqToSwitch:
            nationID = vehicle.typeDescriptor.type.id[0]
            notifications = avatar_getter.getSoundNotifications()
            if notifications:
                notifications.clear()
            SoundGroups.g_instance.soundModes.setCurrentNation(nations.NAMES[nationID])
        self.onVehicleControlling(vehicle)
        if not vehicle.isAlive():
            self.onVehicleStateUpdated(VEHICLE_VIEW_STATE.DESTROYED, None)
        else:
            self.__updateTI.start()
        return
Example #27
0
class DamageLog(object):
    def __init__(self):
        self.msgNoAlt = []
        self.msgAlt = []
        self.isDownAlt = False
        self.lastHit = ''
        self.currentTime = ''
        self.isAlive = True
        self.oldHealth = None
        self.maxHealth = None
        self.lineFire = -1
        self.totalFireDmg = 0
        self.lineFireOld = -1
        self.numberFire = 0
        self.timerLastHit = None
        self.timerReloadAttacker = None
        self.copyMacros = {}
        self.macros = {
            'number': 0,
            'critical-hit': '',
            'vehicle': '',
            'name': '',
            'vtype': '',
            'clan': '',
            'c:costShell': 'do_not_know',
            'dmg-kind': '',
            'c:dmg-kind': '',
            'c:vtype': '',
            'type-shell': '',
            'costShell': 'do_not_know',
            'dmg': '',
            'timer': 0,
            'c:team-dmg': '',
            'c:hit-effects': '',
            'comp-name': '',
            'level': '',
            'clanicon': '',
            'clannb': '',
            'marksOnGun': '',
            'squad-num': None,
            'dmg-ratio': '',
            'hit-effects': '',
            'team-dmg': '',
            'c:type-shell': '',
            'splash-hit': ''
        }
        self.data = {
            'attackReasonID': 0,
            'n': 0,
            'maxHitEffectCode': -1,
            'isFire': False,
            'splash-hit': 'no-splash',
            'compName': 'do_not_know',
            'dmg': 0
        }
        self.config = {}

    def reset(self):
        self.msgNoAlt = []
        self.msgAlt = []
        self.isDownAlt = False
        self.lastHit = ''
        self.currentTime = ''
        self.isAlive = True
        self.oldHealth = None
        self.maxHealth = None
        self.lineFire = -1
        self.totalFireDmg = 0
        self.lineFireOld = -1
        self.numberFire = 0
        if (self.timerLastHit is not None) and (self.timerLastHit.isStarted):
            self.timerLastHit.stop()
        if (self.timerReloadAttacker
                is not None) and (self.timerReloadAttacker.isStarted):
            self.timerReloadAttacker.stop()
        self.copyMacros = {}
        self.macros = {
            'number': 0,
            'critical-hit': '',
            'vehicle': '',
            'name': '',
            'vtype': '',
            'clan': '',
            'c:costShell': 'do_not_know',
            'dmg-kind': '',
            'c:dmg-kind': '',
            'c:vtype': '',
            'type-shell': '',
            'costShell': 'do_not_know',
            'dmg': '',
            'timer': 0,
            'c:team-dmg': '',
            'c:hit-effects': '',
            'comp-name': '',
            'level': '',
            'clanicon': '',
            'clannb': '',
            'marksOnGun': '',
            'squad-num': None,
            'dmg-ratio': '',
            'hit-effects': '',
            'team-dmg': '',
            'c:type-shell': '',
            'splash-hit': ''
        }
        self.data = {
            'attackReasonID': 0,
            'n': 0,
            'maxHitEffectCode': -1,
            'isFire': False,
            'splash-hit': 'no-splash',
            'compName': 'do_not_know',
            'dmg': 0
        }
        self.config = {}

    def parser(self, strHTML, fire=False):
        old_strHTML = ''
        while old_strHTML != strHTML:
            old_strHTML = strHTML
            if fire:
                for s in MACROS_NAME:
                    strHTML = strHTML.replace('{{' + s + '}}',
                                              str(self.copyMacros[s]))
            else:
                for s in MACROS_NAME:
                    strHTML = strHTML.replace('{{' + s + '}}',
                                              str(self.macros[s]))
        return strHTML

    def addStringLog(self):
        if self.data['attackReasonID'] == 1:
            if self.lineFireOld > -1:
                if self.lineFire > -1:
                    self.lineFireOld = self.lineFire
                self.msgNoAlt[self.lineFireOld] = self.parser(
                    config.get('damageLog/log/formatHistory'), True)
                self.msgAlt[self.lineFireOld] = self.parser(
                    config.get('damageLog/log/formatHistoryAlt'), True)
                if self.lineFire == -1:
                    self.lineFireOld = self.lineFire
            else:
                self.copyMacros = self.macros.copy()
                self.msgNoAlt.insert(
                    0, self.parser(config.get('damageLog/log/formatHistory')))
                self.msgAlt.insert(
                    0,
                    self.parser(config.get('damageLog/log/formatHistoryAlt')))
                self.lineFireOld = self.lineFire
        else:
            self.msgNoAlt.insert(
                0, self.parser(config.get('damageLog/log/formatHistory')))
            self.msgAlt.insert(
                0, self.parser(config.get('damageLog/log/formatHistoryAlt')))
            self.numberFire += 1
        as_event('ON_HIT')

    def hideLastHit(self):
        self.lastHit = ''
        self.timerLastHit.stop()
        as_event('ON_LAST_HIT')

    def updateLastHit(self):
        timeDisplayLastHit = float(
            config.get('damageLog/lastHit/timeDisplayLastHit'))
        self.lastHit = self.parser(
            config.get('damageLog/lastHit/formatLastHit'))  #, True)
        if self.lastHit:
            if (self.timerLastHit
                    is not None) and (self.timerLastHit.isStarted):
                self.timerLastHit.stop()
            self.timerLastHit = TimeInterval(timeDisplayLastHit, self,
                                             'hideLastHit')
            self.timerLastHit.start()
            as_event('ON_LAST_HIT')

    def afterTimerReload(self):
        self.currentTime = ''
        self.timerReloadAttacker.stop()
        as_event('ON_TIMER_RELOAD')

    def currentTimeReload(self):
        self.macros['timer'] = round(self.finishTime - BigWorld.serverTime(),
                                     1)
        self.config['timeTextAfterReload'] = float(
            config.get('damageLog/timeReload/timeTextAfterReload'))
        if self.macros['timer'] > 0:
            self.currentTime = self.parser(
                config.get('damageLog/timeReload/formatTimer'))
        else:
            self.timerReloadAttacker.stop()
            if self.config['timeTextAfterReload'] > 0:
                self.timerReloadAttacker = TimeInterval(
                    self.config['timeTextAfterReload'], self,
                    'afterTimerReload')
                self.currentTime = self.parser(
                    config.get('damageLog/timeReload/formatTimerAfterReload'))
                self.timerReloadAttacker.start()
            else:
                self.currentTime = ''
        as_event('ON_TIMER_RELOAD')

    def timeReload(self):
        reload_orig = self.data['typeDescriptor'].gun['reloadTime']
        crew = 0.94 if self.data['typeDescriptor'].miscAttrs[
            'crewLevelIncrease'] != 0 else 1
        if (self.data['typeDescriptor'].gun['clip'][0] == 1) and (
                self.data['typeDescriptor'].miscAttrs['gunReloadTimeFactor'] !=
                0):
            rammer = self.data['typeDescriptor'].miscAttrs[
                'gunReloadTimeFactor']
        else:
            rammer = 1
        self.macros['timer'] = round(reload_orig * crew * rammer, 1)

        self.currentTime = self.parser(
            config.get('damageLog/timeReload/formatTimer'))
        as_event('ON_TIMER_RELOAD')
        self.finishTime = self.macros['timer'] + BigWorld.serverTime()
        if (self.timerReloadAttacker
                is not None) and (self.timerReloadAttacker.isStarted):
            self.timerReloadAttacker.stop()
        self.timerReloadAttacker = TimeInterval(0.1, self, 'currentTimeReload')
        self.timerReloadAttacker.start()

    def readyConfig(self, section):
        self.config['vehicleClass'] = keyLower(config.get(section + 'vtype'))
        self.config['colorShell'] = keyLower(
            config.get(section + 'c:costShell'))
        self.config['costShell'] = keyLower(config.get(section + 'costShell'))
        self.config['color_type_hit'] = keyLower(
            keyLower(config.get(section + 'c:dmg-kind')))
        self.config['colorVehicleClass'] = keyLower(
            config.get(section + 'c:vtype'))
        self.config['type_hit'] = keyLower(config.get(section + 'dmg-kind'))
        self.config['c:team-dmg'] = keyLower(config.get(section +
                                                        'c:team-dmg'))
        self.config['team-dmg'] = keyLower(config.get(section + 'team-dmg'))
        self.config['compNames'] = keyLower(config.get(section + 'comp-name'))
        self.config['splash-hit'] = keyLower(config.get(section +
                                                        'splash-hit'))
        if self.data['maxHitEffectCode'] == 5:
            self.config['critical-hit'] = config.get(section +
                                                     'critical-hit/critical')
        else:
            self.config['critical-hit'] = config.get(
                section + 'critical-hit/no-critical')
        self.config['showHitNoDamage'] = config.get(section +
                                                    'showHitNoDamage')
        self.config['hitEffect'] = keyLower(config.get(section +
                                                       'hit-effects'))
        self.config['colorHitEffect'] = keyLower(
            config.get(section + 'c:hit-effects'))
        self.config['type-shell'] = keyLower(config.get(section +
                                                        'type-shell'))
        self.config['c:type-shell'] = keyLower(
            config.get(section + 'c:type-shell'))

    def setMacros(self):
        self.macros['c:team-dmg'] = self.config['c:team-dmg'].get(
            self.data['team-dmg'], '')
        self.macros['team-dmg'] = self.config['team-dmg'].get(
            self.data['team-dmg'], '')
        self.macros['vtype'] = self.config['vehicleClass'].get(
            self.data['attackerVehicleType'], 'not_vehicle')
        self.macros['c:costShell'] = self.config['colorShell'].get(
            self.data['costShell'])
        self.macros['costShell'] = self.config['costShell'].get(
            self.data['costShell'])
        self.macros['c:dmg-kind'] = self.config['color_type_hit'].get(
            ATTACK_REASONS[self.data['attackReasonID']])
        self.macros['dmg-kind'] = self.config['type_hit'].get(
            ATTACK_REASONS[self.data['attackReasonID']],
            'reason: %s' % self.data['attackReasonID'])
        self.macros['c:vtype'] = self.config['colorVehicleClass'].get(
            self.data['attackerVehicleType'], 'not_vehicle')
        self.macros['comp-name'] = self.config['compNames'].get(
            self.data['compName'], '')
        self.macros['splash-hit'] = self.config['splash-hit'].get(
            self.data['splash-hit'], '')
        self.macros['critical-hit'] = self.config['critical-hit']
        self.macros['type-shell'] = self.config['type-shell'].get(
            self.data['shellKind'], '')
        self.macros['c:type-shell'] = self.config['c:type-shell'].get(
            self.data['shellKind'], '')
        self.macros['c:hit-effects'] = self.config['colorHitEffect'].get(
            self.data['HIT_EFFECT_CODE'])
        self.macros['hit-effects'] = self.config['hitEffect'][
            self.data['HIT_EFFECT_CODE']]
        self.macros['dmg'] = self.data['dmg']
        self.macros['dmg-ratio'] = self.data['dmg-ratio']

    def groupDamageFire(self):
        if self.data['attackReasonID'] == 1 and config.get(
                'damageLog/log/groupDamagesFromFire'):
            if (self.lineFire == -1) and (self.lineFireOld == -1):
                self.lineFire = 0
                self.data['n'] += 1
            else:
                self.copyMacros['dmg'] += self.data['dmg']
                self.copyMacros['dmg-ratio'] += self.data['dmg-ratio']
        else:
            if (self.config['showHitNoDamage']) or (self.data['isDamage']):
                self.data['n'] += 1
                if self.lineFire > -1:
                    self.lineFire += 1

    def updateData(self):
        player = BigWorld.player()
        self.data['dmg-ratio'] = self.data['dmg'] * 100 // self.maxHealth
        if self.data['attackerID'] != 0:
            attacker = player.arena.vehicles.get(self.data['attackerID'])
            entity = BigWorld.entity(self.data['attackerID'])
            statXVM = _stat.players.get(self.data['attackerID'])
            self.data['team-dmg'] = 'do_not_know'
            if attacker['team'] != player.team:
                self.data['team-dmg'] = 'enemy-dmg'
            elif attacker['name'] == player.name:
                self.data['team-dmg'] = 'player'
            else:
                self.data['team-dmg'] = 'ally-dmg'
            self.data['typeDescriptor'] = attacker['vehicleType']
            self.data['vehCD'] = attacker['vehicleType'].type.compactDescr
            self.data['attackerVehicleType'] = list(
                attacker['vehicleType'].type.tags.intersection(
                    VEHICLE_CLASSES))[0].lower()
            self.data['shortUserString'] = self.data[
                'typeDescriptor'].type.shortUserString
            self.data['name'] = attacker['name']
            self.data['clanAbbrev'] = attacker['clanAbbrev']
            self.data['level'] = self.data['typeDescriptor'].level
            self.data['clanicon'] = _stat.getClanIcon(self.data['attackerID'])
            if (statXVM is not None) and (statXVM.squadnum > 0):
                self.data['squadnum'] = statXVM.squadnum
            else:
                self.data['squadnum'] = ''
            if entity is not None:
                self.data['marksOnGun'] = '_' + str(
                    entity.publicInfo['marksOnGun'])
            else:
                self.data['marksOnGun'] = ''
        else:
            self.data['team-dmg'] = 'do_not_know'
            self.data['typeDescriptor'] = None
            self.data['vehCD'] = None
            self.data['attackerVehicleType'] = ''
            self.data['shortUserString'] = ''
            self.data['name'] = ''
            self.data['clanAbbrev'] = ''
            self.data['level'] = ''
            self.data['clanicon'] = ''
            self.data['squadnum'] = ''
            self.data['marksOnGun'] = ''
        self.updateMacros()

    def updateMacros(self):
        self.readyConfig('damageLog/log/')
        self.groupDamageFire()
        self.config['marksOnGun'] = config.get('texts/marksOnGun')
        if self.data['isFire'] and (self.data['attackReasonID'] == 1):
            self.macros['dmg'] = self.copyMacros['dmg']
        else:

            self.macros['dmg'] = self.data['dmg']
            self.macros['number'] = '{:0>2}'.format(self.data['n'])
            self.macros['vehicle'] = self.data['shortUserString']
            self.macros['name'] = self.data['name']
            self.macros['clannb'] = self.data['clanAbbrev']
            self.macros['clan'] = '[' + self.data[
                'clanAbbrev'] + ']' if self.data['clanAbbrev'] else ''
            self.macros['level'] = self.data['level']
            self.macros['clanicon'] = self.data.get('clanicon', '')
            self.macros['marksOnGun'] = self.config['marksOnGun'].get(
                self.data['marksOnGun'], '')
            self.macros['squad-num'] = self.data['squadnum']
            self.setMacros()
        if self.config['showHitNoDamage']:
            self.addStringLog()
        elif self.data['isDamage']:
            self.addStringLog()
        self.readyConfig('damageLog/lastHit/')
        self.setMacros()
        if self.data['isFire'] and (self.data['attackReasonID'] == 1):
            self.macros['dmg'] = self.copyMacros['dmg']
        if self.config['showHitNoDamage']:
            self.updateLastHit()
        elif self.data['isDamage']:
            self.updateLastHit()
        if (self.data['attackReasonID']
                == 0) and (self.data['attackerID'] != 0):
            self.readyConfig('damageLog/timeReload/')
            self.setMacros()
            self.timeReload()
        if self.data['attackReasonID'] == 1 and config.get(
                'damageLog/log/groupDamagesFromFire'):
            self.data['isFire'] = True
        if self.lineFireOld == -1:
            self.data['isFire'] = False

    def typeShell(self, effectsIndex):
        if (self.data['attackerID'] == 0) or (self.data['attackReasonID']
                                              not in [0, 100]):
            self.data['costShell'] = 'do_not_know'
            self.data['shellKind'] = 'not_shell'
            return
        player = BigWorld.player()
        attacker = player.arena.vehicles.get(self.data['attackerID'])
        self.data['costShell'] = 'do_not_know'
        for shell in attacker['vehicleType'].gun['shots']:
            if effectsIndex == shell['shell']['effectsIndex']:
                self.data['shellKind'] = str(shell['shell']['kind']).lower()
                xmlPath = ITEM_DEFS_PATH + 'vehicles/' + nations.NAMES[
                    shell['shell']['id'][0]] + '/components/shells.xml'
                for name, subsection in ResMgr.openSection(xmlPath).items():
                    if name != 'icons':
                        xmlCtx = (None, xmlPath + '/' + name)
                        if _xml.readInt(xmlCtx, subsection, 'id', 0,
                                        65535) == shell['shell']['id'][1]:
                            price = _xml.readPrice(xmlCtx, subsection, 'price')
                            self.data['costShell'] = 'gold-shell' if price[
                                1] else 'silver-shell'
                            break
                ResMgr.purge(xmlPath, True)
                break

    def showDamageFromShot(self, vehicle, attackerID, points, effectsIndex,
                           damageFactor):
        if vehicle.isPlayerVehicle and self.isAlive:
            self.isAlive = vehicle.health > 0
            self.data['isDamage'] = damageFactor > 0
            maxHitEffectCode, decodedPoints = DamageFromShotDecoder.decodeHitPoints(
                points, vehicle.typeDescriptor)
            self.data['compName'] = decodedPoints[
                0].componentName if decodedPoints else 'do_not_know'
            self.data['maxHitEffectCode'] = maxHitEffectCode
            self.data['attackReasonID'] = 0
            self.data['attackerID'] = attackerID
            self.data['isDamage'] = damageFactor > 0
            self.data['splash-hit'] = 'no-splash'
            if (effectsIndex == 24) or (effectsIndex == 25):
                self.data['attackReasonID'] = effectsIndex
            self.typeShell(effectsIndex)
            if (maxHitEffectCode < 4):
                self.data['HIT_EFFECT_CODE'] = HIT_EFFECT_CODES[
                    maxHitEffectCode]
                self.data['dmg'] = 0
                self.updateData()
            elif (maxHitEffectCode == 5) and (damageFactor == 0):
                self.data['HIT_EFFECT_CODE'] = 'armor_pierced_no_damage'
                self.data['dmg'] = 0
                self.updateData()
            elif maxHitEffectCode == 4:
                self.data['HIT_EFFECT_CODE'] = 'armor_pierced'

    def showDamageFromExplosion(self, vehicle, attackerID, center,
                                effectsIndex, damageFactor):
        if vehicle.isPlayerVehicle and self.isAlive:
            self.isAlive = vehicle.health > 0
            self.data['isDamage'] = damageFactor > 0
            # log('damageFactor = %s' % damageFactor)
            self.data['splash-hit'] = 'splash'
            self.data['attackerID'] = attackerID
            if (effectsIndex == 24) or (effectsIndex == 25):
                self.data['attackReasonID'] = effectsIndex
            self.typeShell(effectsIndex)
            if (damageFactor == 0):
                self.data['HIT_EFFECT_CODE'] = 'armor_pierced_no_damage'
                self.data['dmg'] = 0
                self.updateData()

    def onHealthChanged(self, vehicle, newHealth, attackerID, attackReasonID):
        if vehicle.isPlayerVehicle:
            if (attackReasonID != 0) or (self.data['attackReasonID']
                                         not in [24, 25]):  # [24, 25, 100]):
                self.data['attackReasonID'] = attackReasonID
            self.data['isDamage'] = True
            if (attackReasonID != 0):  # and (attackReasonID != 100):
                self.data['costShell'] = 'do_not_know'
                self.data['shellKind'] = 'not_shell'
            self.data['attackerID'] = attackerID
            self.data['dmg'] = self.oldHealth - newHealth
            self.oldHealth = newHealth
            self.data['HIT_EFFECT_CODE'] = 'armor_pierced'
            self.updateData()
Example #28
0
class _EngineStateHandler(_StateHandler):
    """
    The class provides logic to track engine state changes and vehicle movement changes.
    All logic is based on changes of the current gear.
    """
    __slots__ = ('__weakref__', '__gear', '__vehMoveAnimTimer', '__engineStartAnimTimer')

    def __init__(self, updater, vehicle):
        """
        Constructor. Initializes internal variables based on vehicle state.
        
        :param updater: An instance of _VehicleUpdater class, that creates this handler.
        :param vehicle: Vehicle to be tracked.
        :return:
        """
        super(_EngineStateHandler, self).__init__(updater)
        if vehicle is not None and vehicle.appearance is not None:
            self.__gear = vehicle.appearance.gear
        else:
            self.__gear = _STOPPED_ENGINE_GEAR
        self.__vehMoveAnimTimer = TimeInterval(_VEHICLE_ANIM_DURATION, self, '_stopVehMoveAnim')
        self.__engineStartAnimTimer = TimeInterval(_VEHICLE_ANIM_DURATION, self, '_stopEngineStartAnim')
        return

    def clear(self):
        """
        Resets internal variables.
        """
        self.__gear = _STOPPED_ENGINE_GEAR
        self._stopVehMoveAnim()
        self._stopEngineStartAnim()

    def _invalidate(self, vehicle):
        """
        The method determines whether one of the following events has occurred and exposes the
        appropriate state change to the updater:
            1. Vehicle starts moving.
            2. Engine is started.
        By these events, appropriate animations are run on UI. To stop animations appropriate state
        change event is sent in _VEHICLE_ANIM_DURATION time. Note that animation duration depends
        on sound effect (track length). But right now there is no way to determine effect duration.
        Therefore for all vehicles the same constant is used.
        
        :param vehicle: A reference to the tracked vehicle(BW entity).
        :return: The state change if any. Otherwise an empty list.
        """
        states = []
        if vehicle.appearance is not None:
            gear = vehicle.appearance.gear
            if self.__gear != gear:
                if not self.__gear and gear > 0:
                    if not self.__vehMoveAnimTimer.isStarted():
                        states.append((VEHICLE_VIEW_STATE.VEHICLE_MOVEMENT_STATE, True))
                        self.__vehMoveAnimTimer.start()
                elif self.__gear == _STOPPED_ENGINE_GEAR and gear >= 0:
                    if not self.__engineStartAnimTimer.isStarted():
                        states.append((VEHICLE_VIEW_STATE.VEHICLE_ENGINE_STATE, True))
                        self.__engineStartAnimTimer.start()
                elif self.__gear > 0 and not self.__gear:
                    pass
                elif self.__gear >= 0 and gear == _STOPPED_ENGINE_GEAR:
                    pass
                self.__gear = gear
        return states

    def _stopVehMoveAnim(self):
        """
        Stops 'vehicle start' animation by sending the appropriate event.
        """
        if self.__vehMoveAnimTimer.isStarted():
            self.__vehMoveAnimTimer.stop()
            self.notifyStateChanged(VEHICLE_VIEW_STATE.VEHICLE_MOVEMENT_STATE, False)

    def _stopEngineStartAnim(self):
        """
        Stops 'engine start' animation by sending the appropriate event.
        """
        if self.__engineStartAnimTimer.isStarted():
            self.__engineStartAnimTimer.stop()
            self.notifyStateChanged(VEHICLE_VIEW_STATE.VEHICLE_ENGINE_STATE, False)
Example #29
0
class DebugPanel(UIInterface):
    __UPDATE_INTERVAL = 0.01

    def __init__(self, parentUI):
        UIInterface.__init__(self)
        self.__ui = parentUI
        self.__timeInterval = None
        self.__performanceStats = _PerformanceStats()
        self.__performanceStats.populateUI(parentUI)
        return

    def start(self):
        self.__timeInterval = TimeInterval(self.__UPDATE_INTERVAL, self, '_DebugPanel__update')
        self.__timeInterval.start()
        self.__update()

    def destroy(self):
        self.__performanceStats.disposeUI()
        self.__performanceStats = None
        self.__timeInterval.stop()
        return

    def __update(self):
        player = BigWorld.player()
        if player is None or not hasattr(player, 'playerVehicleID'):
            return
        else:
            fps = 0
            recordedFps = -1
            ping = 0
            isLaggingNow = False
            replayCtrl = BattleReplay.g_replayCtrl
            if replayCtrl.isPlaying and replayCtrl.fps > 0:
                fps = BigWorld.getFPS()[1]
                recordedFps = replayCtrl.fps
                ping = replayCtrl.ping
                isLaggingNow = replayCtrl.isLaggingNow
            else:
                isLaggingNow = player.filter.isLaggingNow
                if not isLaggingNow:
                    for v in BigWorld.entities.values():
                        if _isVehicleEntity(v):
                            if not v.isPlayer:
                                if v.isAlive() and isinstance(v.filter, BigWorld.WGVehicleFilter) and v.filter.isLaggingNow:
                                    isLaggingNow = True
                                    break

                ping = min(BigWorld.LatencyInfo().value[3] * 1000, 999)
                if ping < 999:
                    ping = max(1, ping - 500.0 * constants.SERVER_TICK_LENGTH)
                fpsInfo = BigWorld.getFPS()
                from helpers.statistics import g_statistics
                g_statistics.update(fpsInfo, ping, isLaggingNow)
                fps = fpsInfo[1]
                if replayCtrl.isRecording:
                    replayCtrl.setFpsPingLag(fps, ping, isLaggingNow)
            try:
                self.__performanceStats.updateDebugInfo(int(fps), int(ping), isLaggingNow, int(recordedFps))
            except:
                pass

            return
class _VehicleUpdater(object):
    """
    The class implements logic for tracking changes of vehicle parameters in equal time intervals.
    It encapsulates different algorithms of tracking based on vehicle type. The inner logic is
    based on the custom state handlers (classes derived from _StateHandler).
    """

    def __init__(self, vehCtrl, vehicleID):
        """
        Constructor. Initializes internal variables.
        
        :param vehCtrl: Reference to vehicle state controller owning this updater.
        :param vehicleID: Unique identifier of vehicle to be tracked
        """
        super(_VehicleUpdater, self).__init__()
        self.__isAlive = True
        self.__handlers = None
        self.__ctrl = weakref.proxy(vehCtrl)
        self.__vehicleID = vehicleID
        self.__updateTI = None
        self._setUpHandlers()
        return

    def handleStateChange(self, state, value):
        """
        Represents a hook to catch states changes before the vehicle state controller propagates
        them to subscribers. Redirects the call to each handler to perform required logic.
        
        :param state: A state listed within VEHICLE_VIEW_STATE
        :param value: State value
        :return: True if any handler returns True. Otherwise - False.
        """
        isStateHandled = False
        for handler in self.__handlers:
            isStateHandled |= handler.handleStateChange(state, value)

        return isStateHandled

    def switch(self, vehicleID):
        """
        Switches the updater to another vehicle: reset internal states and handlers.
        
        :param vehicleID: Unique identifier of a new vehicle that will be tracked
        """
        self.clear()
        self.__vehicleID = vehicleID
        self._setUpHandlers()
        return self

    def start(self):
        """
        Sets up and starts the timer to invalidate handlers.
        """
        if self.__updateTI is None:
            self.__updateTI = TimeInterval(VEHICLE_UPDATE_INTERVAL, self, '_update')
        self.__updateTI.start()
        return

    def stop(self):
        """
        Stops and clears running timer (if any).
        """
        if self.__updateTI is not None:
            self.__updateTI.stop()
            self.__updateTI = None
        return

    def clear(self):
        """
        Clears internal variables and stops timer.
        """
        self.stop()
        if self.__handlers is not None:
            for handler in self.__handlers:
                handler.clear()

            self.__handlers = None
        self.__vehicleID = None
        return

    def notifyStateChanged(self, state, value):
        """
        The helper method to provide handler ability to notify subscribers about changes of
        vehicle's states through the vehicle state controller.
        
        :param state: A state listed within VEHICLE_VIEW_STATE
        :param value: State value.
        """
        self.__ctrl.notifyStateChanged(state, value)

    def _update(self):
        """
        Callback on timer tick event. Initiates invalidation of all handlers, get all states
        changes and redirects them to the vehicle state controller by emitting appropriate events.
        """
        states = []
        vehicle = BigWorld.entity(self.__vehicleID)
        if vehicle is not None and vehicle.isStarted:
            if not vehicle.isAlive() and self.__isAlive:
                self.__isAlive = False
                states.append((VEHICLE_VIEW_STATE.DESTROYED, None))
            for handler in self.__handlers:
                newStates = handler(vehicle)
                states.extend(newStates)

        for item in states:
            self.notifyStateChanged(*item)

        return

    def _setUpHandlers(self):
        """
        Determines a list of handlers based on vehicle type and sets up them.
        """
        vehicle = BigWorld.entity(self.__vehicleID)
        if vehicle is not None:
            isPlayerVehicle = vehicle.isPlayerVehicle
            if isPlayerVehicle:
                self.__handlers = (_SpeedStateHandler(self, True), _RpmStateHandler(self, vehicle), _EngineStateHandler(self, vehicle))
            else:
                self.__handlers = (_HealthStateHandler(self),
                 _SpeedStateHandler(self, False),
                 _RpmStateHandler(self, vehicle),
                 _EngineStateHandler(self, vehicle))
        return
Example #31
0
class BaseMarkerController(IArenaVehiclesController):
    _UPDATE_TICK_LENGTH = 0.01

    def __init__(self):
        super(BaseMarkerController, self).__init__()
        self.onTickUpdate = Event.Event()
        self._gui = None
        self._attachGUIToMarkersCallback = {}
        self._markers = {}
        self._updateTI = None
        self._globalVisibility = True
        return

    def init(self):
        _logger.debug('BaseMarkerController.init')
        self._gui = MarkerGUIProvider(self.getPluginID())
        g_eventBus.addListener(events.GameEvent.GUI_VISIBILITY,
                               self._handleGUIVisibility,
                               scope=EVENT_BUS_SCOPE.BATTLE)

    @property
    def allMarkers(self):
        return self._markers.values()

    @property
    def allMarkersID(self):
        return self._markers.keys()

    def getPluginID(self):
        raise NotImplementedError

    def createMarker(self, matrix, markerType, clazz=AreaMarker, bitMask=0):
        markerData = MarkerParamsFactory.getMarkerParams(
            matrix, markerType, bitMask)
        return clazz(markerData)

    def addMarker(self, marker):
        markerID = marker.markerID
        if markerID in self._markers:
            _logger.error('Marker with Id=%s exists already', markerID)
            marker.clear()
            return None
        else:
            self._attachGUIToMarkersCallback[markerID] = BigWorld.callback(
                0, partial(self._attachGUIToMarkers, markerID))
            self._checkGlobalVisibilityForMarker(marker)
            self._markers[markerID] = marker
            self.checkStartTimer()
            return markerID

    def setMarkerMatrix(self, markerID, matrix):
        marker = self._markers.get(markerID, None)
        if marker:
            marker.setMatrix(matrix)
        return

    def removeMarker(self, markerID):
        if markerID not in self._markers:
            return
        else:
            if markerID in self._attachGUIToMarkersCallback:
                BigWorld.cancelCallback(
                    self._attachGUIToMarkersCallback[markerID])
                self._attachGUIToMarkersCallback.pop(markerID)
            else:
                self._markers[markerID].detachGUI()
            self._markers[markerID].clear()
            self._markers.pop(markerID, None)
            return

    def removeAllMarkers(self):
        for markerID in self._markers:
            if markerID in self._attachGUIToMarkersCallback:
                BigWorld.cancelCallback(
                    self._attachGUIToMarkersCallback[markerID])
                self._attachGUIToMarkersCallback.pop(markerID)
            else:
                self._markers[markerID].detachGUI()
            self._markers[markerID].clear()

        self._markers.clear()

    def showMarkers(self, unblock=True):
        if not self._globalVisibility:
            return
        for markerID in self._markers.iterkeys():
            self.showMarkersById(markerID, unblock)

        self.checkStartTimer()

    def hideMarkers(self, block=True):
        for marker in self._markers.values():
            marker.setVisible(False)
            if block:
                marker.blockChangVisibility = True

        if self._updateTI is not None:
            self._updateTI.stop()
        return

    def showMarkersById(self, markerID, unblock=True):
        player = BigWorld.player()
        marker = self._markers.get(markerID, None)
        if marker:
            if unblock:
                marker.blockChangVisibility = False
            if not self._globalVisibility:
                return
            if marker.isEmpty():
                return
            conditionDistance = marker.disappearingRadius
            if conditionDistance > 0:
                distanceToArea = BaseMarkerController.getDistanceToArea(
                    marker, player)
                hide = conditionDistance < distanceToArea if marker.reverseDisappearing else conditionDistance > distanceToArea
                if hide:
                    marker.setVisible(False)
                    return
            marker.setVisible(True)
        self.checkStartTimer()
        return

    def hideMarkersById(self, markerID, block=True):
        if markerID in self._markers.keys():
            marker = self._markers[markerID]
            marker.setVisible(False)
            if block:
                marker.blockChangVisibility = True

    def getMarkerById(self, markerID):
        return self._markers.get(markerID)

    @staticmethod
    def getDistanceToArea(marker, player):
        absDistance = (marker.getMarkerPosition() -
                       player.getOwnVehiclePosition()).length
        distanceToArea = max(0, absDistance - marker.areaRadius)
        return distanceToArea

    def start(self):
        if self._gui is None:
            return
        else:
            if self._updateTI:
                self._updateTI.stop()
            for markerID in self._markers.iterkeys():
                if markerID not in self._attachGUIToMarkersCallback:
                    self._attachGUIToMarkersCallback[
                        markerID] = BigWorld.callback(
                            0.0,
                            partial(self._attachGUIToMarkers,
                                    markerID=markerID))

            self._updateTI = TimeInterval(self._UPDATE_TICK_LENGTH, self,
                                          '_tickUpdate')
            self._updateTI.start()
            return

    def checkStartTimer(self):
        if self._markers and self._updateTI and not self._updateTI.isStarted():
            self.start()

    def stop(self):
        if self._updateTI is not None:
            self._updateTI.stop()
            self._updateTI = None
        self._clear()
        return

    def checkStopTimer(self):
        if not self._markers and self._updateTI and self._updateTI.isStarted():
            self._updateTI.stop()

    def _tickUpdate(self):
        self.onTickUpdate()
        self.checkStopTimer()

    def _clear(self):
        g_eventBus.removeListener(events.GameEvent.GUI_VISIBILITY,
                                  self._handleGUIVisibility,
                                  scope=EVENT_BUS_SCOPE.BATTLE)
        self.removeAllMarkers()
        self._gui = None
        return

    def _attachGUIToMarkers(self, markerID):
        self._attachGUIToMarkersCallback[markerID] = None
        if self._gui and markerID in self._markers:
            marker = self._markers[markerID]
            if self._checkInitedPlugin(marker):
                self._attachGUIToMarkersCallback.pop(markerID)
                self._markers[markerID].attachGUI(self._gui)
                return
        self._attachGUIToMarkersCallback[markerID] = BigWorld.callback(
            0, partial(self._attachGUIToMarkers, markerID))
        return

    def _handleGUIVisibility(self, event):
        self._globalVisibility = event.ctx['visible']
        if self._globalVisibility:
            self.showMarkers(unblock=False)
        else:
            self.hideMarkers(block=False)

    def _checkInitedPlugin(self, marker):
        if marker.hasMarker2D() and self._gui.getMarkers2DPlugin() is None:
            return False
        else:
            return False if marker.hasMinimap(
            ) and self._gui.getMinimapPlugin() is None else True

    def _checkGlobalVisibilityForMarker(self, marker):
        if not self._globalVisibility:
            marker.setVisible(False)
Example #32
0
class DebugController(IViewComponentsController):
    """Controller for the debug panel.
    
    This class starts internal update cycle and updates debug panel.
    In order to collect lagging info from near vehicles, these vehicle's ids
    should be provided from outside using special methods.
    """

    def __init__(self):
        super(DebugController, self).__init__()
        self._debugPanelUI = None
        self._timeInterval = None
        self._visibleVehicles = set()
        return

    def getControllerID(self):
        return BATTLE_CTRL_ID.DEBUG

    def startControl(self):
        self._timeInterval = TimeInterval(_UPDATE_INTERVAL, self, '_update')
        self._timeInterval.start()

    def stopControl(self):
        self._timeInterval.stop()
        self._timeInterval = None
        self._debugPanelUI = None
        self._visibleVehicles = set()
        return

    def setViewComponents(self, debugPanelUI):
        raise isinstance(debugPanelUI, IDebugPanel) or AssertionError
        self._debugPanelUI = debugPanelUI

    def clearViewComponents(self):
        self._debugPanelUI = None
        return

    def startVehicleVisual(self, vehicleID):
        if avatar_getter.getPlayerVehicleID() != vehicleID:
            self._visibleVehicles.add(vehicleID)

    def stopVehicleVisual(self, vehicleID):
        self._visibleVehicles.discard(vehicleID)

    def _update(self):
        replayCtrl = BattleReplay.g_replayCtrl
        if replayCtrl.isPlaying and replayCtrl.fps > 0:
            fps = BigWorld.getFPS()[1]
            fpsReplay = int(replayCtrl.fps)
            ping = replayCtrl.ping
            isLaggingNow = replayCtrl.isLaggingNow
        else:
            fpsReplay = -1
            player = BigWorld.player()
            isLaggingNow = player.filter.isLaggingNow if player is not None else False
            if not isLaggingNow:
                for vehicleID in self._visibleVehicles:
                    vehicle = BigWorld.entities[vehicleID]
                    if vehicle is not None and vehicle.isAlive():
                        try:
                            if vehicle.filter.isLagginNow:
                                isLaggingNow = True
                                break
                        except AttributeError:
                            pass

            avgLatency = BigWorld.LatencyInfo().value[3]
            if avgLatency:
                ping = min(avgLatency * 1000, 999)
                if ping < 999:
                    ping = max(1, ping - 500.0 * constants.SERVER_TICK_LENGTH)
            else:
                ping = 999
            fpsInfo = BigWorld.getFPS()
            g_statistics.update(fpsInfo, ping, isLaggingNow)
            fps = fpsInfo[1]
            if replayCtrl.isRecording:
                replayCtrl.setFpsPingLag(fps, ping, isLaggingNow)
        if self._debugPanelUI is not None:
            self._debugPanelUI.updateDebugInfo(int(ping), int(fps), isLaggingNow, fpsReplay=fpsReplay)
        return