def __playEffect(self, kind, *modifs):
     self.__stopEffects()
     if kind == 'empty' or self.__vehicle is None:
         return
     else:
         enableDecal = True
         if kind in ('explosion', 'destruction') and self.isFlying:
             enableDecal = False
         if self.isUnderwater:
             if kind not in ('submersionDeath', ):
                 return
         effects = self.typeDescriptor.type.effects[kind]
         if not effects:
             return
         vehicle = self.__vehicle
         effects = random.choice(effects)
         self.__effectsPlayer = EffectsListPlayer(
             effects[1],
             effects[0],
             showShockWave=vehicle.isPlayerVehicle,
             showFlashBang=vehicle.isPlayerVehicle,
             isPlayer=vehicle.isPlayerVehicle,
             showDecal=enableDecal,
             start=vehicle.position + Math.Vector3(0.0, 1.0, 0.0),
             end=vehicle.position + Math.Vector3(0.0, -1.0, 0.0),
             entity_id=vehicle.id)
         self.__effectsPlayer.play(self.__compoundModel, *modifs)
         return
예제 #2
0
 def addNew(self, matProv, effectsList, keyPoints, **args):
     desc = EffectsListPlayer(effectsList,
                              keyPoints,
                              position=(self.__nodeName, matProv),
                              **args)
     desc.play(self.__model, None, partial(self._effects.remove, desc))
     self._effects.append(desc)
예제 #3
0
 def attach(self):
     if self.__player is None:
         self.__player = EffectsListPlayer(self.__timeLine.effectsList,
                                           self.__timeLine.keyPoints,
                                           node=self.__node.node)
     self.__player.play(self.__model)
     return
예제 #4
0
 def __playPullEffect(self, effectMaterialIdx):
     self.__stopPullEffects()
     stages, effectsList, _ = self.__detachmentEffectsDesc['pull'][
         effectMaterialIdx]
     self.__pullEffectListPlayer = EffectsListPlayer(effectsList, stages)
     self.__pullEffectListPlayer.play(self.__turretModel,
                                      SpecialKeyPointNames.START)
     self.__pullEffectListPlayer.effectMaterialIdx = effectMaterialIdx
예제 #5
0
 def addNewToNode(self, node, matProv, effectsList, keyPoints, waitForKeyOff = False, **args):
     if not node and matProv is None:
         position = None
     else:
         position = (node, matProv)
     desc = EffectsListPlayer(effectsList, keyPoints, position=position, **args)
     desc.play(self.__model, None, partial(self._effects.remove, desc), waitForKeyOff)
     self._effects.append(desc)
     return desc
 def addNewToNode(self, node, matProv, effectsList, keyPoints, waitForKeyOff=False, **args):
     if not node and matProv is None:
         position = None
     else:
         position = (node, matProv)
     desc = EffectsListPlayer(effectsList, keyPoints, position=position, **args)
     desc.play(self.__model, None, partial(self._effects.remove, desc), waitForKeyOff)
     self._effects.append(desc)
     return desc
 def __playEffect(self, model, effectName):
     effectsCache = self.customizableObjectsMgr.effectsCache
     if effectName in effectsCache:
         effect = effectsCache[effectName]
         effectPlayer = EffectsListPlayer(effect.effectsList,
                                          effect.keyPoints)
         effectPlayer.play(model)
     else:
         effectPlayer = MapActivities.startActivity(effectName)
     return effectPlayer
예제 #8
0
 def playEffect(self):
     if self.__effectsPlayer is not None:
         return
     elif self.__model is None:
         return
     else:
         if self.__effectsTimeLine is not None:
             self.__effectsPlayer = EffectsListPlayer(self.__effectsTimeLine.effectsList, self.__effectsTimeLine.keyPoints)
             self.__effectsPlayer.play(self.__model)
         return
예제 #9
0
 def __playPullEffect(self, effectMaterialIdx):
     self.__stopPullEffects()
     result = self.__detachmentEffectsDesc['pull'].get(
         effectMaterialIdx, None)
     if result is None:
         return
     else:
         stages, effectsList, _ = result
         self.__pullEffectListPlayer = EffectsListPlayer(
             effectsList, stages)
         self.__pullEffectListPlayer.play(self.__turretModel,
                                          SpecialKeyPointNames.START)
         self.__pullEffectListPlayer.effectMaterialIdx = effectMaterialIdx
         return
예제 #10
0
 def _start(self, data, args):
     data['_isStarted'] = False
     vehicle = data['entity']
     isUnderwater = vehicle.appearance.isUnderwater
     data['wasUnderwater'] = isUnderwater
     if not isUnderwater:
         stages, effects, _ = random.choice(vehicle.typeDescriptor.type.effects['flaming'])
         data['entity_id'] = vehicle.id
         effectListPlayer = EffectsListPlayer(effects, stages, **data)
         data['_effectsPlayer'] = effectListPlayer
         effectListPlayer.play(vehicle.appearance.compoundModel, None, None, True)
     data['_isStarted'] = True
     vehicle.appearance.switchFireVibrations(True)
     return
예제 #11
0
 def checkUnderwater(self, vehicle, isVehicleUnderwater):
     data = vehicle.extras[self.index]
     wasUnderwater = data.get('wasUnderwater', False)
     if isVehicleUnderwater and not wasUnderwater:
         if '_effectsPlayer' in data:
             effectsListPlayer = data['_effectsPlayer']
             effectsListPlayer.stop()
             del data['_effectsPlayer']
     if not isVehicleUnderwater and wasUnderwater:
         stages, effects, _ = random.choice(vehicle.typeDescriptor.type.effects['flaming'])
         data['entity_id'] = vehicle.id
         effectListPlayer = EffectsListPlayer(effects, stages, **data)
         data['_effectsPlayer'] = effectListPlayer
         effectListPlayer.play(vehicle.appearance.compoundModel, None, None, True)
     data['wasUnderwater'] = isVehicleUnderwater
     return
예제 #12
0
 def playEffect(self):
     if self.__effectsPlayer is not None:
         return
     else:
         if self.__effectsTimeLine is not None:
             self.__effectsPlayer = EffectsListPlayer(self.__effectsTimeLine.effectsList, self.__effectsTimeLine.keyPoints)
             self.__effectsPlayer.play(self.__model)
         return
예제 #13
0
    def _start(self, data, args):
        data['_isStarted'] = False
        vehicle = data['entity']
        isUnderwater = vehicle.appearance.isUnderwater
        data['wasUnderwater'] = isUnderwater
        if not isUnderwater:
            (stages, effects, _,) = random.choice(vehicle.typeDescriptor.type.effects['flaming'])
            data['modelMap'] = {}
            for (i, j,) in vehicle.appearance.modelsDesc.iteritems():
                data['modelMap'][i] = vehicle.appearance.modelsDesc[i]['model']

            data['entity_id'] = vehicle.id
            effectListPlayer = EffectsListPlayer(effects, stages, **data)
            data['_effectsPlayer'] = effectListPlayer
            effectListPlayer.play(vehicle.appearance.modelsDesc['hull']['model'], None, None, True)
        data['_isStarted'] = True
        vehicle.appearance.switchFireVibrations(True)
 def __createEffectPlayer(self, effectName):
     effect = self.__customizableObjectsMgr.getEffect(effectName)
     if effect is None:
         return
     else:
         effectPlayer = EffectsListPlayer(effect.effectsList,
                                          effect.keyPoints)
         return effectPlayer
예제 #15
0
 def _start(self, data, burstCount):
     vehicle = data['entity']
     gunDescr = vehicle.typeDescriptor.gun
     stages, effects, _ = gunDescr['effects']
     data['entity_id'] = vehicle.id
     data['_effectsListPlayer'] = EffectsListPlayer(effects, stages, **data)
     data['_burst'] = (burstCount, gunDescr['burst'][1])
     data['_gunModel'] = vehicle.appearance.compoundModel
     self.__doShot(data)
예제 #16
0
    def checkUnderwater(self, data, vehicle, isVehicleUnderwater):
        wasUnderwater = data.get('wasUnderwater', False)
        if isVehicleUnderwater and not wasUnderwater:
            if '_effectsPlayer' in data:
                effectsListPlayer = data['_effectsPlayer']
                effectsListPlayer.stop()
                del data['_effectsPlayer']
        if not isVehicleUnderwater and wasUnderwater:
            (stages, effects, _,) = random.choice(vehicle.typeDescriptor.type.effects['flaming'])
            data['modelMap'] = {}
            for (i, j,) in vehicle.appearance.modelsDesc.iteritems():
                data['modelMap'][i] = vehicle.appearance.modelsDesc[i]['model']

            data['entity_id'] = vehicle.id
            effectListPlayer = EffectsListPlayer(effects, stages, **data)
            data['_effectsPlayer'] = effectListPlayer
            effectListPlayer.play(vehicle.appearance.modelsDesc['hull']['model'], None, None, True)
        data['wasUnderwater'] = isVehicleUnderwater
 def __playEffect(self, effectName, model):
     if self.__effectsPlayer is not None or None in (model, effectName):
         return
     else:
         effectsSection = destructible_entities.g_destructibleEntitiesCache.getDestroyEffectList(
             effectName)
         if effectsSection is None:
             return
         effects = effectsFromSection(effectsSection)
         if effects is None:
             return
         fakeModel = helpers.newFakeModel()
         BigWorld.player().addModel(fakeModel)
         tmpMatrix = Math.Matrix(self.__visualModel.matrix)
         fakeModel.position = tmpMatrix.translation
         self.__effectsPlayer = EffectsListPlayer(effects.effectsList,
                                                  effects.keyPoints)
         self.__effectsPlayer.play(fakeModel, None)
         return
예제 #18
0
    def _start(self, data, args):
        data['_isStarted'] = False
        vehicle = data['entity']
        isUnderwater = vehicle.appearance.isUnderwater
        data['wasUnderwater'] = isUnderwater
        if not isUnderwater:
            stages, effects, _ = random.choice(
                vehicle.typeDescriptor.type.effects['flaming'])
            data['modelMap'] = {}
            for i, j in vehicle.appearance.modelsDesc.iteritems():
                data['modelMap'][i] = vehicle.appearance.modelsDesc[i]['model']

            data['entity_id'] = vehicle.id
            effectListPlayer = EffectsListPlayer(effects, stages, **data)
            data['_effectsPlayer'] = effectListPlayer
            effectListPlayer.play(
                vehicle.appearance.modelsDesc['hull']['model'], None, None,
                True)
        data['_isStarted'] = True
        vehicle.appearance.switchFireVibrations(True)
예제 #19
0
 def _start(self, data, burstCount):
     if not _isAllowedToStart():
         return
     vehicle = data['entity']
     gunDescr = vehicle.typeDescriptor.gun
     stages, effects, _ = gunDescr['effects']
     data['_effectsListPlayer'] = EffectsListPlayer(effects, stages)
     data['_burst'] = (burstCount, gunDescr['burst'][1])
     data['_gunModel'] = vehicle.appearance.modelsDesc['gun']['model']
     if vehicle.isPlayer:
         BigWorld.addAlwaysUpdateModel(data['_gunModel'])
     self.__doShot(data)
예제 #20
0
    def checkUnderwater(self, data, vehicle, isVehicleUnderwater):
        wasUnderwater = data.get('wasUnderwater', False)
        if isVehicleUnderwater and not wasUnderwater:
            if '_effectsPlayer' in data:
                effectsListPlayer = data['_effectsPlayer']
                effectsListPlayer.stop()
                del data['_effectsPlayer']
        if not isVehicleUnderwater and wasUnderwater:
            stages, effects, _ = random.choice(
                vehicle.typeDescriptor.type.effects['flaming'])
            data['modelMap'] = {}
            for i, j in vehicle.appearance.modelsDesc.iteritems():
                data['modelMap'][i] = vehicle.appearance.modelsDesc[i]['model']

            data['entity_id'] = vehicle.id
            effectListPlayer = EffectsListPlayer(effects, stages, **data)
            data['_effectsPlayer'] = effectListPlayer
            effectListPlayer.play(
                vehicle.appearance.modelsDesc['hull']['model'], None, None,
                True)
        data['wasUnderwater'] = isVehicleUnderwater
예제 #21
0
    def _start(self, data, burstCount):
        vehicle = data['entity']
        gunDescr = vehicle.typeDescriptor.gun
        stages, effects, _ = gunDescr['effects']
        data['modelMap'] = {}
        for i, j in vehicle.appearance.modelsDesc.iteritems():
            data['modelMap'][i] = vehicle.appearance.modelsDesc[i]['model']

        data['entity_id'] = vehicle.id
        data['_effectsListPlayer'] = EffectsListPlayer(effects, stages, **data)
        data['_burst'] = (burstCount, gunDescr['burst'][1])
        data['_gunModel'] = vehicle.appearance.modelsDesc['gun']['model']
        self.__doShot(data)
 def addNew(self, position, effectsList, keyPoints, callbackOnStop, **args):
     model = helpers.newFakeModel()
     model.position = position
     BigWorld.player().addModel(model)
     direction = args.get('dir', None)
     if direction is not None:
         model.rotate(direction.yaw, (0.0, 1.0, 0.0))
     self.__incrementalEffectID += 1
     effectID = self.__incrementalEffectID
     desc = dict()
     desc['model'] = model
     desc['effectsPlayer'] = EffectsListPlayer(effectsList, keyPoints, **args)
     desc['effectsPlayer'].play(model, None, partial(self.__callbackBeforeDestroy, effectID, callbackOnStop), args.get('waitForKeyOff', False))
     self._models[effectID] = desc
     return effectID
예제 #23
0
    def __readHeroEffects(self):
        if not self.effectsXmlPath:
            return
        else:
            rootSection = ResMgr.openSection(self.effectsXmlPath)
            if rootSection is None:
                return
            effectsSection = rootSection['effects']
            if effectsSection is None:
                return
            for effectValues in effectsSection.values():
                name = effectValues.name
                effect = effectsFromSection(effectValues)
                player = EffectsListPlayer(effect.effectsList,
                                           effect.keyPoints)
                self.__effects[name] = player

            return
예제 #24
0
    def _start(self, data, args):
        burstCount, gunIndex = args
        if burstCount != self._SHOT_SINGLE:
            data['_gunIndex'] = range(0, burstCount)
        else:
            data['_gunIndex'] = [gunIndex]
        vehicle = data['entity']
        gunDescr = vehicle.typeDescriptor.gun
        data['entity_id'] = vehicle.id
        effectPlayers = {}
        for gunIndex in data['_gunIndex']:
            stages, effects, _ = gunDescr.effects[gunIndex]
            effectPlayers[gunIndex] = EffectsListPlayer(effects, stages, **data)

        data['_effectsListPlayers'] = effectPlayers
        data['_burst'] = (burstCount, gunDescr.burst[1])
        data['_gunModel'] = vehicle.appearance.compoundModel
        self.__doShot(data)
 def __playEffects(self, model, regularEffectName, hangingEffectName):
     hangingEffectPlayer = None
     if regularEffectName in self.__effectsCache:
         regularEffect = self.__effectsCache[regularEffectName]
         regularEffectPlayer = EffectsListPlayer(regularEffect.effectsList,
                                                 regularEffect.keyPoints)
         regularEffectPlayer.play(model)
     else:
         regularEffectPlayer = MapActivities.startActivity(
             regularEffectName)
     if self.customizableObjectsMgr.state:
         if hangingEffectName in self.__effectsCache:
             hangingEffect = self.__effectsCache[hangingEffectName]
             hangingEffectPlayer = EffectsListPlayer(
                 hangingEffect.effectsList, hangingEffect.keyPoints)
             hangingEffectPlayer.play(model)
         else:
             hangingEffectPlayer = MapActivities.startActivity(
                 hangingEffectName)
     return (regularEffectPlayer, hangingEffectPlayer)
 def __playEffect(self, kind, *modifs):
     self.__stopEffects()
     if kind == 'empty' or self.__vehicle is None:
         return
     else:
         enableDecal = True
         if not self.__isPillbox and kind in ('explosion', 'destruction'):
             filter = self.__vehicle.filter
             isFlying = filter.numLeftTrackContacts < 2 and filter.numRightTrackContacts < 2
             if isFlying:
                 enableDecal = False
         if self.isUnderwater:
             if kind not in ('submersionDeath',):
                 return
         effects = self.typeDescriptor.type.effects[kind]
         if not effects:
             return
         vehicle = self.__vehicle
         effects = random.choice(effects)
         self.__effectsPlayer = EffectsListPlayer(effects[1], effects[0], showShockWave=vehicle.isPlayerVehicle, showFlashBang=vehicle.isPlayerVehicle, isPlayer=vehicle.isPlayerVehicle, showDecal=enableDecal, start=vehicle.position + Math.Vector3(0.0, -1.0, 0.0), end=vehicle.position + Math.Vector3(0.0, 1.0, 0.0), entity_id=vehicle.id)
         self.__effectsPlayer.play(self.__compoundModel, *modifs)
         return
예제 #27
0
 def addNew(self, position, effectsList, stages, callbackOnStop, **args):
     replayCtrl = BattleReplay.g_replayCtrl
     if replayCtrl.isPlaying and replayCtrl.isTimeWarpInProgress:
         return -1
     else:
         model = BigWorld.player().newFakeModel()
         model.position = position
         BigWorld.addModel(model)
         BigWorld.addAlwaysUpdateModel(model)
         dir = args.get('dir', None)
         if dir is not None:
             model.rotate(dir.yaw, (0.0, 1.0, 0.0))
         self.__incrementalEffectID += 1
         effectID = self.__incrementalEffectID
         desc = dict()
         desc['model'] = model
         desc['effectsPlayer'] = EffectsListPlayer(effectsList, stages,
                                                   **args)
         desc['effectsPlayer'].play(
             model, None,
             partial(self.__callbackBeforeDestroy, effectID,
                     callbackOnStop))
         self._models[effectID] = desc
         return effectID
예제 #28
0
class NodeEffectList(BaseNodeEffect):
    __slots__ = ('__node', '__player', '__model', '__timeLine')

    def __init__(self, name, model, node):
        super(NodeEffectList, self).__init__()
        self.__node = node
        self.__model = model
        from CustomEffect import getEffectList
        self.__timeLine = getEffectList(name)
        self.__player = None
        return

    def __del__(self):
        if self.__player is not None:
            self.__player.stop()
        self.__node = None
        self.__model = None
        self.__timeLine = None
        self.__player = None
        return

    def attach(self):
        if self.__player is None:
            self.__player = EffectsListPlayer(self.__timeLine.effectsList,
                                              self.__timeLine.keyPoints,
                                              node=self.__node.node)
        self.__player.play(self.__model)
        return

    def detach(self):
        if self.__player is not None:
            self.__player.stop()
        return

    def deactivate(self):
        if self.__player is not None:
            self.__player.stop()
        return
예제 #29
0
class CompoundAppearance(ComponentSystem, CallbackDelayer):
    compoundModel = property(lambda self: self.__compoundModel)
    boundEffects = property(lambda self: self.__boundEffects)
    fashion = property(lambda self: self.__fashions.chassis)
    typeDescriptor = property(lambda self: self.__typeDesc)
    id = property(lambda self: self.__vID)
    isAlive = property(lambda self: self.__isAlive)
    isObserver = property(lambda self: self.__isObserver)

    def __setFashions(self, fashions, isTurretDetached = False):
        self.__fashions = fashions
        self.__fashion = fashions.chassis
        if isTurretDetached:
            self.__compoundModel.setupFashions((fashions.chassis, fashions.hull))
        else:
            self.__compoundModel.setupFashions(fashions)

    fashions = property(lambda self: self.__fashions, __setFashions)
    terrainMatKind = property(lambda self: self.__currTerrainMatKind)
    terrainEffectMaterialNames = property(lambda self: self.__terrainEffectMaterialNames)
    isInWater = property(lambda self: self.waterSensor.isInWater)
    isUnderwater = property(lambda self: self.waterSensor.isUnderWater)
    waterHeight = property(lambda self: self.waterSensor.waterHeight)
    damageState = property(lambda self: self.__currentDamageState)
    frameTimeStamp = 0
    rightTrackScroll = property(lambda self: self.__rightTrackScroll)
    leftTrackScroll = property(lambda self: self.__leftTrackScroll)
    splineTracks = property(lambda self: self.__splineTracks)
    activated = property(lambda self: self.__activated)
    isFlying = property(lambda self: self.flyingInfoProvider is not None and self.flyingInfoProvider.isFlying)
    isLeftSideFlying = property(lambda self: self.flyingInfoProvider is not None and self.flyingInfoProvider.isLeftSideFlying)
    isRightSideFlying = property(lambda self: self.flyingInfoProvider is not None and self.flyingInfoProvider.isRightSideFlying)

    @property
    def rpm(self):
        if self.detailedEngineState is not None:
            return self.detailedEngineState.rpm
        else:
            return 0.0

    @property
    def gear(self):
        if self.detailedEngineState is not None:
            return self.detailedEngineState.gearNum
        else:
            return 0.0

    trackScrollController = property(lambda self: self.__trackScrollCtl)
    filter = AutoProperty()
    detailedEngineState = ComponentDescriptor()
    engineAudition = ComponentDescriptor()
    trackCrashAudition = ComponentDescriptor()
    customEffectManager = ComponentDescriptor()
    highlighter = ComponentDescriptor()
    gunRecoil = ComponentDescriptor()
    gunLinkedNodesAnimator = ComponentDescriptor()
    swingingAnimator = ComponentDescriptor()
    suspensionSound = ComponentDescriptor()
    siegeEffects = ComponentDescriptor()
    lodCalculator = ComponentDescriptor()
    frictionAudition = ComponentDescriptor()
    suspension = ComponentDescriptor()
    leveredSuspension = ComponentDescriptor()
    suspensionController = ComponentDescriptor()
    wheelsAnimator = ComponentDescriptor()
    trackNodesAnimator = ComponentDescriptor()
    vehicleTraces = ComponentDescriptor()
    flyingInfoProvider = ComponentDescriptor()
    terrainMatKindSensor = ComponentDescriptor()
    waterSensor = ComponentDescriptor()
    peripheralsController = ComponentDescriptor()

    def __init__(self):
        CallbackDelayer.__init__(self)
        ComponentSystem.__init__(self)
        self.turretMatrix = Math.WGAdaptiveMatrixProvider()
        self.gunMatrix = Math.WGAdaptiveMatrixProvider()
        self.__vehicle = None
        self.__filter = None
        self.__originalFilter = None
        self.__typeDesc = None
        self.__fashion = None
        self.__crashedTracksCtrl = None
        self.__currentDamageState = VehicleDamageState()
        self.__effectsPlayer = None
        self.__engineMode = (0, 0)
        self.__currTerrainMatKind = [-1] * _MATKIND_COUNT
        self.__terrainEffectMaterialNames = [''] * _MATKIND_COUNT
        self.__chassisDecal = VehicleDecal(self)
        self.__splodge = None
        self.__vehicleStickers = None
        self.onModelChanged = Event()
        self.__leftTrackScroll = 0.0
        self.__rightTrackScroll = 0.0
        self.__fashions = None
        self.__compoundModel = None
        self.__boundEffects = None
        self.__splineTracks = None
        self.flyingInfoProvider = Vehicular.FlyingInfoProvider()
        self.__trackScrollCtl = BigWorld.PyTrackScroll()
        self.__trackScrollCtl.setFlyingInfo(DataLinks.createBoolLink(self.flyingInfoProvider, 'isLeftSideFlying'), DataLinks.createBoolLink(self.flyingInfoProvider, 'isRightSideFlying'))
        self.__weaponEnergy = 0.0
        self.__activated = False
        self.__systemStarted = False
        self.__vID = 0
        self.__isAlive = True
        self.__isTurretDetached = False
        self.__periodicTimerID = None
        self.__wasDeactivated = False
        self.__inSpeedTreeCollision = False
        self.__isObserver = False
        return

    def prerequisites(self, typeDescriptor, vID, health, isCrewActive, isTurretDetached, outfitCD):
        self.__currentDamageState.update(health, isCrewActive, False)
        outfit = Outfit(outfitCD)
        out = camouflages.getCamoPrereqs(outfit, typeDescriptor)
        splineDesc = typeDescriptor.chassis.splineDesc
        if splineDesc is not None:
            out.append(splineDesc.segmentModelLeft)
            out.append(splineDesc.segmentModelRight)
            if splineDesc.segment2ModelLeft is not None:
                out.append(splineDesc.segment2ModelLeft)
            if splineDesc.segment2ModelRight is not None:
                out.append(splineDesc.segment2ModelRight)
        self.__vID = vID
        self.__typeDesc = typeDescriptor
        self.__isTurretDetached = isTurretDetached
        return out

    def setVehicle(self, vehicle):
        self.__vehicle = vehicle
        if self.customEffectManager is not None:
            self.customEffectManager.setVehicle(vehicle)
        if self.__crashedTracksCtrl is not None:
            self.__crashedTracksCtrl.setVehicle(vehicle)
        if self.frictionAudition is not None:
            self.frictionAudition.setVehicleMatrix(vehicle.matrix)
        self.highlighter.setVehicle(vehicle)
        self.__applyVehicleOutfit()
        return

    def __arenaPeriodChanged(self, period, *otherArgs):
        if self.detailedEngineState is None:
            return
        else:
            periodEndTime = BigWorld.player().arena.periodEndTime
            serverTime = BigWorld.serverTime()
            engine_state.notifyEngineOnArenaPeriodChange(self.detailedEngineState, period, periodEndTime, serverTime)
            return

    def activate(self):
        if self.__activated or self.__vehicle is None:
            return
        else:
            super(CompoundAppearance, self).activate()
            isPlayerVehicle = self.__vehicle.isPlayerVehicle
            self.__isObserver = 'observer' in self.__typeDesc.type.tags
            player = BigWorld.player()
            self.__originalFilter = self.__vehicle.filter
            self.__vehicle.filter = self.__filter
            self.__vehicle.filter.enableStabilisedMatrix(isPlayerVehicle)
            self.__filter.isStrafing = self.__vehicle.isStrafing
            self.__filter.vehicleCollisionCallback = player.handleVehicleCollidedVehicle
            self.__compoundModel.isHighPriorityReflection = isPlayerVehicle
            if isPlayerVehicle:
                if player.inputHandler is not None:
                    player.inputHandler.addVehicleToCameraCollider(self.__vehicle)
                self.__inSpeedTreeCollision = True
                BigWorld.setSpeedTreeCollisionBody(self.__compoundModel.getBoundsForPart(TankPartIndexes.HULL))
            self.__linkCompound()
            if not self.__isObserver:
                self.__chassisDecal.attach()
            self.__createAndAttachStickers()
            self.__startSystems()
            self.setupGunMatrixTargets()
            if not self.__isObserver:
                self.__vehicle.filter.enableLagDetection(not self.__currentDamageState.isCurrentModelDamaged)
            self.onModelChanged()
            if self.lodCalculator is not None:
                self.lodCalculator.setupPosition(DataLinks.linkMatrixTranslation(self.__compoundModel.matrix))
            if hasattr(self.filter, 'placingCompensationMatrix') and self.swingingAnimator is not None:
                self.swingingAnimator.placingCompensationMatrix = self.filter.placingCompensationMatrix
                self.swingingAnimator.worldMatrix = self.__compoundModel.matrix
            if self.__periodicTimerID is not None:
                BigWorld.cancelCallback(self.__periodicTimerID)
            self.__periodicTimerID = BigWorld.callback(_PERIODIC_TIME, self.__onPeriodicTimer)
            if self.fashion is not None:
                self.fashion.activate()
            if self.__isObserver:
                self.__compoundModel.visible = False
            BigWorld.player().arena.onPeriodChange += self.__arenaPeriodChanged
            BigWorld.player().inputHandler.onCameraChanged += self.__onCameraChanged
            if self.detailedEngineState is not None:
                engine_state.checkEngineStart(self.detailedEngineState, BigWorld.player().arena.period)
            self.__activated = True
            return

    def deactivate(self, stopEffects = True):
        if not self.__activated:
            return
        else:
            self.__activated = False
            self.__wasDeactivated = True
            if self.fashion is not None:
                self.fashion.deactivate()
            self.__stopSystems()
            super(CompoundAppearance, self).deactivate()
            self.__chassisDecal.detach()
            if self.__inSpeedTreeCollision:
                BigWorld.setSpeedTreeCollisionBody(None)
            BigWorld.player().inputHandler.removeVehicleFromCameraCollider(self.__vehicle)
            self.__vehicle.filter.enableLagDetection(False)
            self.turretMatrix.target = None
            self.gunMatrix.target = None
            self.__vehicle.filter = self.__originalFilter
            self.__filter.reset()
            self.__originalFilter = None
            self.__vehicleStickers.detach()
            if stopEffects:
                self.__stopEffects()
                self.__boundEffects.stop()
            self.__vehicle.model = None
            self.__compoundModel.matrix = Math.Matrix()
            self.__vehicle = None
            if self.__crashedTracksCtrl is not None:
                self.__crashedTracksCtrl.deactivate()
            BigWorld.player().arena.onPeriodChange -= self.__arenaPeriodChanged
            BigWorld.player().inputHandler.onCameraChanged -= self.__onCameraChanged
            return

    def __startSystems(self):
        if self.__systemStarted or self.__currentDamageState.isCurrentModelDamaged:
            return
        else:
            if self.flyingInfoProvider is not None:
                self.flyingInfoProvider.setData(self.__vehicle.filter, self.suspension)
            if self.__trackScrollCtl is not None:
                self.__trackScrollCtl.activate()
                self.__trackScrollCtl.setData(self.__vehicle.filter)
            if self.__vehicle.isPlayerVehicle:
                self.delayCallback(_PERIODIC_TIME_ENGINE, self.__onPeriodicTimerEngine)
                self.highlighter.highlight(True)
            if self.engineAudition is not None:
                self.engineAudition.setWeaponEnergy(self.__weaponEnergy)
                self.engineAudition.attachToModel(self.__compoundModel)
            if self.peripheralsController is not None:
                self.peripheralsController.attachToVehicle(self.__vehicle)
            if self.suspensionController is not None:
                self.suspensionController.setData(self.__vehicle.filter, self.__vehicle.typeDescriptor)
            if self.detailedEngineState is not None:
                self.detailedEngineState.onGearUpCbk = self.__onEngineStateGearUp
            self.__systemStarted = True
            return

    def __stopSystems(self):
        if not self.__systemStarted:
            return
        else:
            self.__systemStarted = False
            if self.__periodicTimerID is not None:
                BigWorld.cancelCallback(self.__periodicTimerID)
                self.__periodicTimerID = None
            if self.flyingInfoProvider is not None:
                self.flyingInfoProvider.setData(None, None)
            if self.__vehicle.isPlayerVehicle:
                self.highlighter.highlight(False)
                self.stopCallback(self.__onPeriodicTimerEngine)
            if self.__trackScrollCtl is not None:
                self.__trackScrollCtl.deactivate()
                self.__trackScrollCtl.setData(None)
            if self.detailedEngineState is not None:
                self.detailedEngineState.onGearUpCbk = None
            return

    def __destroySystems(self):
        if self.__periodicTimerID is not None:
            BigWorld.cancelCallback(self.__periodicTimerID)
            self.__periodicTimerID = None
        if self.__trackScrollCtl is not None:
            self.__trackScrollCtl.deactivate()
            self.__trackScrollCtl = None
        if self.__crashedTracksCtrl is not None:
            self.__crashedTracksCtrl.destroy()
            self.__crashedTracksCtrl = None
        self.__systemStarted = False
        return

    def __destroyEngineAudition(self):
        self.engineAudition = None
        if self.detailedEngineState is not None:
            self.detailedEngineState.onEngineStart = None
            self.detailedEngineState.onStateChanged = None
        return

    def __prepareSystemsForDamagedVehicle(self, vehicle, isTurretDetached):
        if self.flyingInfoProvider is not None:
            self.flyingInfoProvider.setData(vehicle.filter, None)
        self.vehicleTraces = None
        self.suspensionSound = None
        self.swingingAnimator = None
        self.gunRecoil = None
        self.gunLinkedNodesAnimator = None
        self.suspension = None
        self.leveredSuspension = None
        self.trackNodesAnimator = None
        self.wheelsAnimator = None
        fashions = VehiclePartsTuple(None, None, None, None)
        self.__setFashions(fashions, isTurretDetached)
        self.customEffectManager = None
        self.__destroyEngineAudition()
        self.detailedEngineState = None
        self.trackCrashAudition = None
        self.frictionAudition = None
        self.terrainMatKindSensor = None
        self.__splineTracks = None
        model = self.compoundModel
        self.waterSensor.sensorPlaneLink = model.root
        self.peripheralsController = None
        self.__destroySystems()
        return

    def destroy(self):
        if self.__vehicle is not None:
            self.deactivate()
        self.__destroySystems()
        ComponentSystem.destroy(self)
        self.__typeDesc = None
        if self.__boundEffects is not None:
            self.__boundEffects.destroy()
        self.__vehicleStickers = None
        self.onModelChanged = None
        self.__chassisDecal.destroy()
        self.__chassisDecal = None
        self.__compoundModel = None
        CallbackDelayer.destroy(self)
        return

    def start(self, prereqs = None):
        for hitTester in self.__typeDesc.getHitTesters():
            hitTester.loadBspModel()

        self.__compoundModel = prereqs[self.__typeDesc.name]
        self.__boundEffects = bound_effects.ModelBoundEffects(self.__compoundModel)
        isCurrentModelDamaged = self.__currentDamageState.isCurrentModelDamaged
        fashions = camouflages.prepareFashions(isCurrentModelDamaged)
        if not isCurrentModelDamaged:
            model_assembler.setupVehicleFashion(fashions.chassis, self.__typeDesc)
        self.__setFashions(fashions, self.__isTurretDetached)
        self.__setupModels()
        if not isCurrentModelDamaged:
            self.__splineTracks = model_assembler.setupSplineTracks(self.__fashion, self.__typeDesc, self.__compoundModel, prereqs)
            self.__crashedTracksCtrl = CrashedTrackController(self.__typeDesc, self.__fashion)
        else:
            self.__trackScrollCtl = None
        if self.__currentDamageState.effect is not None:
            self.__playEffect(self.__currentDamageState.effect, SpecialKeyPointNames.STATIC)
        self.__chassisDecal.create()
        return

    def showStickers(self, show):
        self.__vehicleStickers.show = show

    def updateTurretVisibility(self):
        self.__requestModelsRefresh()

    def changeVisibility(self, modelVisible):
        self.compoundModel.visible = modelVisible
        self.showStickers(modelVisible)
        if self.__crashedTracksCtrl is not None:
            self.__crashedTracksCtrl.setVisible(modelVisible)
        return

    def changeDrawPassVisibility(self, visibilityMask):
        colorPassEnabled = visibilityMask & BigWorld.ColorPassBit != 0
        self.compoundModel.visible = visibilityMask
        self.compoundModel.skipColorPass = not colorPassEnabled
        self.showStickers(colorPassEnabled)
        if self.__crashedTracksCtrl is not None:
            self.__crashedTracksCtrl.setVisible(visibilityMask)
        return

    def onVehicleHealthChanged(self, showEffects = True):
        vehicle = self.__vehicle
        if not vehicle.isAlive() and vehicle.health > 0:
            self.changeEngineMode((0, 0))
        currentState = self.__currentDamageState
        previousState = currentState.state
        isUnderWater = self.waterSensor.isUnderWater
        currentState.update(vehicle.health, vehicle.isCrewActive, isUnderWater)
        if previousState != currentState.state:
            if currentState.effect is not None and showEffects:
                self.__playEffect(currentState.effect)
            if vehicle.health <= 0:
                BigWorld.player().inputHandler.onVehicleDeath(vehicle, currentState.state == 'ammoBayExplosion')
                self.processVehicleDeath(currentState)
                self.__requestModelsRefresh()
            elif not vehicle.isCrewActive:
                self.__onCrewKilled()
        return

    @ComponentSystem.groupCall
    def processVehicleDeath(self, vehicleDamageState):
        pass

    def showAmmoBayEffect(self, mode, fireballVolume):
        if mode == constants.AMMOBAY_DESTRUCTION_MODE.POWDER_BURN_OFF:
            self.__playEffect('ammoBayBurnOff')
            return
        volumes = items.vehicles.g_cache.commonConfig['miscParams']['explosionCandleVolumes']
        candleIdx = 0
        for idx, volume in enumerate(volumes):
            if volume >= fireballVolume:
                break
            candleIdx = idx + 1

        if candleIdx > 0:
            self.__playEffect('explosionCandle%d' % candleIdx)
        else:
            self.__playEffect('explosion')

    def changeEngineMode(self, mode, forceSwinging = False):
        self.__engineMode = mode
        if self.detailedEngineState is not None:
            self.detailedEngineState.mode = self.__engineMode[0]
        if self.__trackScrollCtl is not None:
            self.__trackScrollCtl.setMode(self.__engineMode)
        if BattleReplay.isPlaying() and BattleReplay.g_replayCtrl.isTimeWarpInProgress:
            return
        else:
            return

    def stopSwinging(self):
        if self.swingingAnimator is not None:
            self.swingingAnimator.accelSwingingPeriod = 0.0
        return

    def removeDamageSticker(self, code):
        self.__vehicleStickers.delDamageSticker(code)

    def addDamageSticker(self, code, componentName, stickerID, segStart, segEnd):
        self.__vehicleStickers.addDamageSticker(code, componentName, stickerID, segStart, segEnd)

    def receiveShotImpulse(self, dir, impulse):
        if BattleReplay.isPlaying() and BattleReplay.g_replayCtrl.isTimeWarpInProgress:
            return
        else:
            if not VehicleDamageState.isDamagedModel(self.__currentDamageState.modelState):
                self.swingingAnimator.receiveShotImpulse(dir, impulse)
                if self.__crashedTracksCtrl is not None:
                    self.__crashedTracksCtrl.receiveShotImpulse(dir, impulse)
            return

    def recoil(self):
        gunNode = self.compoundModel.node(TankNodeNames.GUN_INCLINATION)
        impulseDir = Math.Matrix(gunNode).applyVector(Math.Vector3(0, 0, -1))
        impulseValue = self.__typeDesc.gun.impulse
        self.receiveShotImpulse(impulseDir, impulseValue)
        self.gunRecoil.recoil()
        node = self.compoundModel.node('HP_gunFire')
        gunPos = Math.Matrix(node).translation
        BigWorld.player().inputHandler.onVehicleShaken(self.__vehicle, gunPos, impulseDir, self.__typeDesc.shot.shell.caliber, ShakeReason.OWN_SHOT_DELAYED)

    def addCrashedTrack(self, isLeft):
        if not self.__vehicle.isAlive():
            return
        else:
            if self.__crashedTracksCtrl is not None:
                self.__crashedTracksCtrl.addTrack(isLeft, self.isLeftSideFlying if isLeft else self.isRightSideFlying)
            if not self.__vehicle.isEnteringWorld and self.trackCrashAudition:
                self.trackCrashAudition.playCrashSound(isLeft)
            return

    def delCrashedTrack(self, isLeft):
        if self.__crashedTracksCtrl is not None:
            self.__crashedTracksCtrl.delTrack(isLeft)
        if not self.__vehicle.isEnteringWorld and self.trackCrashAudition and self.__vehicle.isPlayerVehicle:
            self.trackCrashAudition.playCrashSound(isLeft, True)
        return

    def __getVehicleOutfit(self):
        if not self.__vehicle:
            return Outfit()
        outfitCD = self.__vehicle.publicInfo['outfit']
        outfit = Outfit(outfitCD)
        if not (self.__vehicle.isPlayerVehicle or outfit.isHistorical()):
            if BigWorld.player().isC11nHistorical:
                outfit = Outfit()
        return outfit

    def __applyVehicleOutfit(self):
        outfit = self.__getVehicleOutfit()
        camouflages.updateFashions(self.__fashions, self.__typeDesc, self.__currentDamageState.isCurrentModelDamaged, outfit)

    def __requestModelsRefresh(self):
        currentModelState = self.__currentDamageState.modelState
        assembler = model_assembler.prepareCompoundAssembler(self.__typeDesc, currentModelState, self.__vehicle.spaceID, self.__vehicle.isTurretDetached)
        BigWorld.loadResourceListBG((assembler,), makeCallbackWeak(self.__onModelsRefresh, currentModelState))

    def __onModelsRefresh(self, modelState, resourceList):
        if not self.damageState.isCurrentModelDamaged:
            raise AssertionError
            return BattleReplay.isFinished() and None
        elif not modelState == self.__currentDamageState.modelState:
            raise AssertionError
            return self.__vehicle is None and None
        else:
            prevTurretYaw = Math.Matrix(self.turretMatrix).yaw
            prevGunPitch = Math.Matrix(self.gunMatrix).pitch
            vehicle = self.__vehicle
            newCompoundModel = resourceList[self.__typeDesc.name]
            self.deactivate(False)
            self.__compoundModel = newCompoundModel
            self.__isTurretDetached = vehicle.isTurretDetached
            self.__prepareSystemsForDamagedVehicle(vehicle, self.__isTurretDetached)
            self.__setupModels()
            self.setVehicle(vehicle)
            self.activate()
            self.__reattachComponents(self.__compoundModel, self.__weaponEnergy)
            self.__filter.syncGunAngles(prevTurretYaw, prevGunPitch)
            model_assembler.setupTurretRotations(self)
            return None

    def __setupModels(self):
        self.__isAlive = not self.__currentDamageState.isCurrentModelDamaged
        if self.__isAlive:
            _, gunLength = self.__computeVehicleHeight()
            self.__weaponEnergy = gunLength * self.__typeDesc.shot.shell.caliber
            self.__setupHavok()
        if MAX_DISTANCE > 0:
            transform = self.__typeDesc.chassis.AODecals[0]
            self.__attachSplodge(BigWorld.Splodge(transform, MAX_DISTANCE, self.__typeDesc.chassis.hullPosition.y))

    def __setupHavok(self):
        vDesc = self.__typeDesc
        node = self.compoundModel.node(TankPartNames.HULL)
        hkm = BigWorld.wg_createHKAttachment(node, vDesc.hull.hitTester.getBspModel())
        if hkm is not None:
            node.attach(hkm)
        node = self.compoundModel.node(TankPartNames.TURRET)
        hkm = BigWorld.wg_createHKAttachment(node, vDesc.turret.hitTester.getBspModel())
        if hkm is not None:
            node.attach(hkm)
        node = self.compoundModel.node(TankPartNames.CHASSIS)
        hkm = BigWorld.wg_createHKAttachment(node, vDesc.chassis.hitTester.getBspModel())
        if hkm is not None:
            node.attach(hkm)
        node = self.compoundModel.node(TankPartNames.GUN)
        hkm = BigWorld.wg_createHKAttachment(node, vDesc.gun.hitTester.getBspModel())
        if hkm is not None:
            node.attach(hkm)
        return

    def __reattachComponents(self, model, weaponEnergy):
        self.__boundEffects.reattachTo(model)
        if self.__effectsPlayer is not None:
            self.__effectsPlayer.reattachTo(model)
        if self.engineAudition is not None:
            self.engineAudition.setWeaponEnergy(weaponEnergy)
            self.engineAudition.attachToModel(model)
        return

    def __playEffect(self, kind, *modifs):
        self.__stopEffects()
        if kind == 'empty' or self.__vehicle is None:
            return
        else:
            enableDecal = True
            if kind in ('explosion', 'destruction') and self.isFlying:
                enableDecal = False
            if self.isUnderwater:
                if kind not in ('submersionDeath',):
                    return
            effects = self.typeDescriptor.type.effects[kind]
            if not effects:
                return
            vehicle = self.__vehicle
            effects = random.choice(effects)
            self.__effectsPlayer = EffectsListPlayer(effects[1], effects[0], showShockWave=vehicle.isPlayerVehicle, showFlashBang=vehicle.isPlayerVehicle, isPlayer=vehicle.isPlayerVehicle, showDecal=enableDecal, start=vehicle.position + Math.Vector3(0.0, -1.0, 0.0), end=vehicle.position + Math.Vector3(0.0, 1.0, 0.0), entity_id=vehicle.id)
            self.__effectsPlayer.play(self.__compoundModel, *modifs)
            return

    __SPORT_ACTIONS_CAMOUFLAGES = {'ussr:T62A_sport': (95, 94),
     'usa:M24_Chaffee_GT': (82, 83)}

    def __getCamouflageParams(self, vDesc, vID):
        vehicleInfo = BigWorld.player().arena.vehicles.get(vID)
        if vehicleInfo is not None:
            camouflageIdPerTeam = CompoundAppearance.__SPORT_ACTIONS_CAMOUFLAGES.get(vDesc.name)
            if camouflageIdPerTeam is not None:
                camouflageId = camouflageIdPerTeam[0] if vehicleInfo['team'] == 1 else camouflageIdPerTeam[1]
                return (camouflageId, time.time(), 100.0)
            camouflagePseudoname = vehicleInfo['events'].get('hunting', None)
            if camouflagePseudoname is not None:
                camouflIdsByNation = {0: {'black': 29,
                     'gold': 30,
                     'red': 31,
                     'silver': 32},
                 1: {'black': 25,
                     'gold': 26,
                     'red': 27,
                     'silver': 28},
                 2: {'black': 52,
                     'gold': 50,
                     'red': 51,
                     'silver': 53},
                 3: {'black': 48,
                     'gold': 46,
                     'red': 47,
                     'silver': 49},
                 4: {'black': 60,
                     'gold': 58,
                     'red': 59,
                     'silver': 61},
                 5: {'black': 56,
                     'gold': 54,
                     'red': 55,
                     'silver': 57},
                 6: {'black': 133,
                     'gold': 134,
                     'red': 135,
                     'silver': 136},
                 7: {'black': 141,
                     'gold': 142,
                     'red': 143,
                     'silver': 144},
                 8: {'black': 154,
                     'gold': 155,
                     'red': 156,
                     'silver': 157}}
                camouflIds = camouflIdsByNation.get(vDesc.type.customizationNationID)
                if camouflIds is not None:
                    ret = camouflIds.get(camouflagePseudoname)
                    if ret is not None:
                        return (ret, time.time(), 100.0)
        arenaType = BigWorld.player().arena.arenaType
        camouflageKind = arenaType.vehicleCamouflageKind
        return vDesc.camouflages[camouflageKind]

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

    def __onCrewKilled(self):
        self.__destroyEngineAudition()
        if self.customEffectManager is not None:
            self.customEffectManager = None
        return

    def onWaterSplash(self, waterHitPoint, isHeavySplash):
        effectName = 'waterCollisionHeavy' if isHeavySplash else 'waterCollisionLight'
        self.__vehicle.showCollisionEffect(waterHitPoint, effectName, Math.Vector3(0.0, 1.0, 0.0))

    def onUnderWaterSwitch(self, isUnderWater):
        if isUnderWater and self.__effectsPlayer is not None and self.__currentDamageState.effect not in ('submersionDeath',):
            self.__stopEffects()
        extra = self.__vehicle.typeDescriptor.extrasDict['fire']
        if extra.isRunningFor(self.__vehicle):
            extra.checkUnderwater(self.__vehicle, isUnderWater)
        return

    def updateTracksScroll(self, leftScroll, rightScroll):
        self.__leftTrackScroll = leftScroll
        self.__rightTrackScroll = rightScroll
        if self.__trackScrollCtl is not None:
            self.__trackScrollCtl.setExternal(leftScroll, rightScroll)
        return

    def __onPeriodicTimerEngine(self):
        if self.detailedEngineState is None or self.engineAudition is None:
            return
        else:
            if self.siegeEffects is not None:
                self.siegeEffects.tick(_PERIODIC_TIME_ENGINE)
            return _PERIODIC_TIME_ENGINE

    def __onPeriodicTimer(self):
        timeStamp = BigWorld.wg_getFrameTimestamp()
        if CompoundAppearance.frameTimeStamp >= timeStamp:
            self.__periodicTimerID = BigWorld.callback(0.0, self.__onPeriodicTimer)
            return
        else:
            CompoundAppearance.frameTimeStamp = timeStamp
            self.__periodicTimerID = BigWorld.callback(_PERIODIC_TIME, self.__onPeriodicTimer)
            if self.__vehicle is None:
                return
            vehicle = self.__vehicle
            if self.peripheralsController is not None:
                self.peripheralsController.update(vehicle, self.__crashedTracksCtrl)
            if not vehicle.isAlive():
                return
            distanceFromPlayer = (BigWorld.camera().position - vehicle.position).length
            self.__updateCurrTerrainMatKinds()
            if not self.__vehicle.isPlayerVehicle:
                if self.siegeEffects is not None:
                    self.siegeEffects.tick(_PERIODIC_TIME)
            self.__updateEffectsLOD(distanceFromPlayer)
            if self.customEffectManager:
                self.customEffectManager.update()
            return

    def __updateEffectsLOD(self, distanceFromPlayer):
        if self.customEffectManager:
            enableExhaust = distanceFromPlayer <= _LOD_DISTANCE_EXHAUST and not self.isUnderwater
            enableTrails = distanceFromPlayer <= _LOD_DISTANCE_TRAIL_PARTICLES and BigWorld.wg_isVehicleDustEnabled()
            self.customEffectManager.enable(enableTrails, EffectSettings.SETTING_DUST)
            self.customEffectManager.enable(enableExhaust, EffectSettings.SETTING_EXHAUST)

    def __updateCurrTerrainMatKinds(self):
        if self.terrainMatKindSensor is None:
            return
        else:
            matKinds = self.terrainMatKindSensor.matKinds
            matKindsCount = len(matKinds)
            for i in xrange(_MATKIND_COUNT):
                matKind = matKinds[i] if i < matKindsCount else 0
                self.__currTerrainMatKind[i] = matKind
                effectIndex = calcEffectMaterialIndex(matKind)
                effectMaterialName = ''
                if effectIndex is not None:
                    effectMaterialName = material_kinds.EFFECT_MATERIALS[effectIndex]
                self.__terrainEffectMaterialNames[i] = effectMaterialName

            if self.vehicleTraces is not None:
                self.vehicleTraces.setCurrTerrainMatKinds(self.__currTerrainMatKind[0], self.__currTerrainMatKind[1])
            return

    def switchFireVibrations(self, bStart):
        if self.peripheralsController is not None:
            self.peripheralsController.switchFireVibrations(bStart)
        return

    def executeHitVibrations(self, hitEffectCode):
        if self.peripheralsController is not None:
            self.peripheralsController.executeHitVibrations(hitEffectCode)
        return

    def executeRammingVibrations(self, matKind = None):
        if self.peripheralsController is not None:
            self.peripheralsController.executeRammingVibrations(self.__vehicle, matKind)
        return

    def executeShootingVibrations(self, caliber):
        if self.peripheralsController is not None:
            self.peripheralsController.executeShootingVibrations(caliber)
        return

    def executeCriticalHitVibrations(self, vehicle, extrasName):
        if self.peripheralsController is not None:
            self.peripheralsController.executeCriticalHitVibrations(vehicle, extrasName)
        return

    def deviceStateChanged(self, deviceName, state):
        if not self.isUnderwater and self.detailedEngineState is not None and deviceName == 'engine':
            engineState = engine_state.getEngineStateFromName(state)
            self.detailedEngineState.engineState = engineState
        return

    def __linkCompound(self):
        vehicle = self.__vehicle
        vehicle.model = None
        vehicle.model = self.__compoundModel
        vehicleMatrix = vehicle.matrix
        self.__compoundModel.matrix = vehicleMatrix
        return

    def __createStickers(self):
        if self.__vehicleStickers is not None:
            return
        else:
            insigniaRank = self.__vehicle.publicInfo['marksOnGun']
            outfit = self.__getVehicleOutfit()
            self.__vehicleStickers = VehicleStickers(self.__typeDesc, insigniaRank, outfit)
            clanID = BigWorld.player().arena.vehicles[self.__vehicle.id]['clanDBID']
            self.__vehicleStickers.setClanID(clanID)
            return

    def __attachStickers(self, alpha = _DEFAULT_STICKERS_ALPHA, emblemsOnly = False):
        raise self.__vehicleStickers is not None or AssertionError
        self.__vehicleStickers.alpha = alpha
        self.__vehicleStickers.attach(self.compoundModel, self.__currentDamageState.isCurrentModelDamaged, not emblemsOnly)
        return

    def __createAndAttachStickers(self):
        isCurrentModelDamaged = self.__currentDamageState.isCurrentModelDamaged
        stickersAlpha = _DEFAULT_STICKERS_ALPHA
        if isCurrentModelDamaged:
            stickersAlpha = items.vehicles.g_cache.commonConfig['miscParams']['damageStickerAlpha']
        self.__createStickers()
        self.__attachStickers(stickersAlpha, isCurrentModelDamaged)

    def __attachSplodge(self, splodge):
        node = self.__compoundModel.node(TankPartNames.HULL)
        if splodge is not None and self.__splodge is None:
            self.__splodge = splodge
            node.attach(splodge)
        return

    def __disableStipple(self):
        self.compoundModel.stipple = False

    def __computeVehicleHeight(self):
        desc = self.__typeDesc
        turretBBox = desc.turret.hitTester.bbox
        gunBBox = desc.gun.hitTester.bbox
        hullBBox = desc.hull.hitTester.bbox
        hullTopY = desc.chassis.hullPosition[1] + hullBBox[1][1]
        turretTopY = desc.chassis.hullPosition[1] + desc.hull.turretPositions[0][1] + turretBBox[1][1]
        gunTopY = desc.chassis.hullPosition[1] + desc.hull.turretPositions[0][1] + desc.turret.gunPosition[1] + gunBBox[1][1]
        return (max(hullTopY, max(turretTopY, gunTopY)), math.fabs(gunBBox[1][2] - gunBBox[0][2]))

    def setupGunMatrixTargets(self, target = None):
        if target is None:
            target = self.__filter
        self.turretMatrix.target = target.turretMatrix
        self.gunMatrix.target = target.gunMatrix
        return

    def onFriction(self, otherID, frictionPoint, state):
        if self.frictionAudition is not None:
            self.frictionAudition.processFriction(otherID, frictionPoint, state)
        return

    def assembleStipple(self):
        compound = self.compoundModel
        compound.matrix = Math.Matrix(compound.matrix)
        hullNode = compound.node(TankPartNames.HULL)
        compound.node(TankPartNames.HULL, hullNode.localMatrix)
        turretRotation = compound.node(TankPartNames.TURRET)
        if turretRotation is not None:
            compound.node(TankPartNames.TURRET, turretRotation.localMatrix)
        gunInclination = compound.node(TankNodeNames.GUN_INCLINATION)
        if gunInclination is not None:
            compound.node(TankNodeNames.GUN_INCLINATION, gunInclination.localMatrix)
        gunRecoil = compound.node(TankNodeNames.GUN_RECOIL)
        if gunRecoil is not None:
            compound.node(TankNodeNames.GUN_RECOIL, gunRecoil.localMatrix)
        self.fashions = VehiclePartsTuple(None, None, None, None)
        return

    def onSiegeStateChanged(self, newState):
        if self.engineAudition is not None:
            self.engineAudition.onSiegeStateChanged(newState)
        if self.suspensionController is not None:
            self.suspensionController.onSiegeStateChanged(newState)
        if self.suspensionSound is not None:
            self.__suspensionSound.vehicleState = newState
        if self.siegeEffects is not None:
            self.siegeEffects.onSiegeStateChanged(newState)
        return

    def __onCameraChanged(self, cameraName, currentVehicleId = None):
        if self.engineAudition is not None:
            self.engineAudition.onCameraChanged(cameraName, currentVehicleId if currentVehicleId is not None else 0)
        return

    def __onEngineStateGearUp(self):
        if self.customEffectManager is not None:
            self.customEffectManager.onGearUp()
        if self.engineAudition is not None:
            self.engineAudition.onEngineGearUp()
        return
예제 #30
0
 def addNew(self, matProv, effectsList, keyPoints, **args):
     desc = EffectsListPlayer(effectsList, keyPoints, position=(self.__nodeName, matProv), **args)
     desc.play(self.__model, None, partial(self._effects.remove, desc))
     self._effects.append(desc)
예제 #31
0
class _TurretDetachmentEffects(object):

    class State:
        FLYING = 0
        ON_GROUND = 1

    __EFFECT_NAMES = {State.FLYING: 'flight',
     State.ON_GROUND: 'flamingOnGround'}
    _MAX_COLLISION_ENERGY = 98.10000000000001
    _MIN_COLLISION_ENERGY = _MIN_COLLISION_SPEED ** 2 * 0.5
    _MIN_NORMALIZED_ENERGY = 0.1
    _DROP_ENERGY_PARAM = 'RTPC_ext_drop_energy'

    def __init__(self, turretModel, detachmentEffectsDesc, onGround):
        self.__turretModel = turretModel
        self.__detachmentEffectsDesc = detachmentEffectsDesc
        self.__stateEffectListPlayer = None
        self.__pullEffectListPlayer = None
        startKeyPoint = SpecialKeyPointNames.START
        if onGround:
            self.__state = self.State.ON_GROUND
            startKeyPoint = SpecialKeyPointNames.STATIC
        else:
            self.__state = self.State.FLYING
        self.__playStateEffect(startKeyPoint)
        return

    def destroy(self):
        self.stopEffects()

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

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

    def stopEffects(self):
        self.__stopStateEffects()
        self.__stopPullEffects()

    def notifyAboutCollision(self, energy, collisionPoint, effectMaterialIdx, groundEffect, underWater):
        if groundEffect:
            stages, effectsList, _ = self.__detachmentEffectsDesc['collision'][effectMaterialIdx]
            normalizedEnergy = self.__normalizeEnergy(energy)
            dropEnergyParam = SoundStartParam(_TurretDetachmentEffects._DROP_ENERGY_PARAM, normalizedEnergy)
            BigWorld.player().terrainEffects.addNew(collisionPoint, effectsList, stages, None, soundParams=(dropEnergyParam,))
        if self.__state != self.State.ON_GROUND:
            self.__state = self.State.ON_GROUND
            if not underWater:
                self.__playStateEffect()
        return

    def notifyAboutBeingPulled(self, isPulled, effectMaterialIdx):
        if isPulled:
            if self.__pullEffectListPlayer is None or self.__pullEffectListPlayer.effectMaterialIdx != effectMaterialIdx:
                self.__playPullEffect(effectMaterialIdx)
        else:
            self.__stopPullEffects()
        return

    def __playPullEffect(self, effectMaterialIdx):
        self.__stopPullEffects()
        stages, effectsList, _ = self.__detachmentEffectsDesc['pull'][effectMaterialIdx]
        self.__pullEffectListPlayer = EffectsListPlayer(effectsList, stages)
        self.__pullEffectListPlayer.play(self.__turretModel, SpecialKeyPointNames.START)
        self.__pullEffectListPlayer.effectMaterialIdx = effectMaterialIdx

    def __playStateEffect(self, startKeyPoint = SpecialKeyPointNames.START):
        self.__stopStateEffects()
        effectName = _TurretDetachmentEffects.__EFFECT_NAMES[self.__state]
        stages, effectsList, _ = self.__detachmentEffectsDesc[effectName]
        self.__stateEffectListPlayer = EffectsListPlayer(effectsList, stages)
        self.__stateEffectListPlayer.play(self.__turretModel, startKeyPoint)

    def __normalizeEnergy(self, energy):
        minBound, maxBound = _TurretDetachmentEffects._MIN_COLLISION_ENERGY, _TurretDetachmentEffects._MAX_COLLISION_ENERGY
        clampedEnergy = mathUtils.clamp(minBound, maxBound, energy)
        t = (clampedEnergy - minBound) / (maxBound - minBound)
        return mathUtils.lerp(_TurretDetachmentEffects._MIN_NORMALIZED_ENERGY, 1.0, t)
예제 #32
0
class _CTFResourcePointModel():

    def __init__(self, pointModelName, effectsSectionName):
        self.__modelFile = None
        self.__model = None
        self.__effectsTimeLine = None
        self.__effectsPlayer = None
        self.__loadTask = None
        self.__hideListener = None
        g_ctfManager.registerResourcePointModel(self)
        modelParams = _g_ctfConfig.readModelParams(pointModelName)
        if modelParams is not None:
            self.__modelFile = modelParams.get('file')
        if self.__modelFile is None:
            LOG_ERROR('%s: can\'t find the "%s" model.' % (_g_ctfConfig.name, pointModelName))
        effectsSection = _g_ctfConfig.readFirstLvlSection(effectsSectionName)
        if effectsSection is not None:
            self.__effectsTimeLine = effectsFromSection(effectsSection)
        return

    def __del__(self):
        self.__hideListener = None
        if self.__loadTask is not None:
            _g_resLoader.stopLoadTask(self.__loadTask)
            self.__loadTask = None
        g_ctfManager.unregisterResourcePointModel(self)
        if self.__effectsPlayer is not None:
            self.stopEffect()
            self.__effectsPlayer = None
        self.__effectsTimeLine = None
        if self.__model is not None:
            BigWorld.delModel(self.__model)
            self.__model = None
        self.__modelFile = None
        return

    def _createPoint(self):
        if g_ctfManager.isNeedHideAll:
            return
        else:
            raise self.__modelFile is not None or AssertionError
            self.__loadTask = _g_resLoader.startLoadTask((self.__modelFile,), self.__onModelLoaded)
            return

    def __onModelLoaded(self, resourceRefs):
        if resourceRefs.failedIDs:
            LOG_ERROR('Failed to load model %s' % (resourceRefs.failedIDs,))
        else:
            model = resourceRefs[self.__modelFile]
            if not model is not None:
                raise AssertionError
                model.position = self.position
                roll, pitch, yaw = self.direction
                model.rotate(roll, (0.0, 0.0, 1.0))
                model.rotate(pitch, (1.0, 0.0, 0.0))
                model.rotate(yaw, (0.0, 1.0, 0.0))
                BigWorld.addModel(model, BigWorld.player().spaceID)
                BigWorld.wg_applyOverlayToModel(model, False)
                self.__model = model
                g_ctfManager.updateRegisteredResourcePointModel(self)
                g_ctfManager.isNeedHideAll and self.__hideResPointFlag()
            else:
                self.__hideListener = _GlobalHideListener(self.__hideResPointFlag)
        return

    def __hideResPointFlag(self):
        if self.__model is not None:
            self.__model.visible = False
        self.stopEffect()
        return

    def playEffect(self):
        if self.__effectsPlayer is not None:
            return
        elif self.__model is None:
            return
        else:
            if self.__effectsTimeLine is not None:
                self.__effectsPlayer = EffectsListPlayer(self.__effectsTimeLine.effectsList, self.__effectsTimeLine.keyPoints)
                self.__effectsPlayer.play(self.__model)
            return

    def stopEffect(self):
        if self.__effectsPlayer is None:
            return
        else:
            self.__effectsPlayer.stop()
            self.__effectsPlayer = None
            return
예제 #33
0
 def __playPullEffect(self, effectMaterialIdx):
     self.__stopPullEffects()
     stages, effectsList, _ = self.__detachmentEffectsDesc['pull'][effectMaterialIdx]
     self.__pullEffectListPlayer = EffectsListPlayer(effectsList, stages)
     self.__pullEffectListPlayer.play(self.__turretModel, SpecialKeyPointNames.START)
     self.__pullEffectListPlayer.effectMaterialIdx = effectMaterialIdx
예제 #34
0
 def __playStateEffect(self, startKeyPoint = SpecialKeyPointNames.START):
     self.__stopStateEffects()
     effectName = _TurretDetachmentEffects.__EFFECT_NAMES[self.__state]
     stages, effectsList, _ = self.__detachmentEffectsDesc[effectName]
     self.__stateEffectListPlayer = EffectsListPlayer(effectsList, stages)
     self.__stateEffectListPlayer.play(self.__turretModel, startKeyPoint)
class CompoundAppearance(ComponentSystem, CallbackDelayer):
    distanceFromPlayer = property(lambda self: self.__distanceFromPlayer)
    compoundModel = property(lambda self: self.__compoundModel)
    boundEffects = property(lambda self: self.__boundEffects)
    fashion = property(lambda self: self.__fashions.chassis)
    filter = property(lambda self: self.__filter)
    typeDescriptor = property(lambda self: self.__typeDesc)
    id = property(lambda self: self.__vID)
    isAlive = property(lambda self: self.__isAlive)

    def __setFashions(self, fashions, isTurretDetached = False):
        self.__fashions = fashions
        self.__fashion = fashions.chassis
        if isTurretDetached:
            self.__compoundModel.setupFashions((fashions.chassis, fashions.hull))
        else:
            self.__compoundModel.setupFashions(fashions)

    fashions = property(lambda self: self.__fashions, __setFashions)
    terrainMatKind = property(lambda self: self.__currTerrainMatKind)
    isInWater = property(lambda self: self.__isInWater)
    isUnderwater = property(lambda self: self.__isUnderWater)
    waterHeight = property(lambda self: self.__waterHeight)
    damageState = property(lambda self: self.__currentDamageState)
    frameTimeStamp = 0
    engineMode = property(lambda self: self.__engineMode)
    rightTrackScroll = property(lambda self: self.__rightTrackScroll)
    leftTrackScroll = property(lambda self: self.__leftTrackScroll)
    gunSound = property(lambda self: self.__gunSound)
    isPillbox = property(lambda self: self.__isPillbox)
    activated = property(lambda self: self.__activated)

    @property
    def rpm(self):
        if self.detailedEngineState is not None:
            return self.detailedEngineState.rpm
        else:
            return 0.0
            return

    @property
    def gear(self):
        if self.detailedEngineState is not None:
            return self.detailedEngineState.gearNum
        else:
            return 0.0
            return

    trackScrollController = property(lambda self: self.__trackScrollCtl)
    detailedEngineState = ComponentDescriptor()
    engineAudition = ComponentDescriptor()
    trackCrashAudition = ComponentDescriptor()
    customEffectManager = ComponentDescriptor()
    highlighter = ComponentDescriptor()
    gunRecoil = ComponentDescriptor()
    swingingAnimator = ComponentDescriptor()
    lodCalculator = ComponentDescriptor()

    def __init__(self):
        CallbackDelayer.__init__(self)
        ComponentSystem.__init__(self)
        self.turretMatrix = Math.WGAdaptiveMatrixProvider()
        self.gunMatrix = Math.WGAdaptiveMatrixProvider()
        self.__vehicle = None
        self.__filter = None
        self.__originalFilter = None
        self.__typeDesc = None
        self.__waterHeight = -1.0
        self.__isInWater = False
        self.__isUnderWater = False
        self.__splashedWater = False
        self.__vibrationsCtrl = None
        self.__lightFxCtrl = None
        self.__auxiliaryFxCtrl = None
        self.__fashion = None
        self.__crashedTracksCtrl = None
        self.__gunRecoil = None
        self.__currentDamageState = VehicleDamageState()
        self.__loadingProgress = 0
        self.__effectsPlayer = None
        self.__engineMode = (0, 0)
        self.__swingMoveFlags = 0
        self.__currTerrainMatKind = [-1] * _MATKIND_COUNT
        self.__leftLightRotMat = None
        self.__rightLightRotMat = None
        self.__leftFrontLight = None
        self.__rightFrontLight = None
        self.__prevVelocity = None
        self.__prevTime = None
        self.__isPillbox = False
        self.__chassisOcclusionDecal = OcclusionDecal()
        self.__chassisShadowForwardDecal = ShadowForwardDecal()
        self.__splodge = None
        self.__vehicleStickers = None
        self.onModelChanged = Event()
        self.__speedInfo = Math.Vector4(0.0, 0.0, 0.0, 0.0)
        self.__wasOnSoftTerrain = False
        self.__vehicleMatrixProv = None
        self.__leftTrackScroll = 0.0
        self.__rightTrackScroll = 0.0
        self.__distanceFromPlayer = 0.0
        self.__fashions = None
        self.__compoundModel = None
        self.__boundEffects = None
        self.__swingingAnimator = None
        self.__splineTracks = None
        self.__customEffectManager = None
        self.__trackScrollCtl = BigWorld.PyTrackScroll()
        self.__weaponEnergy = 0.0
        self.__activated = False
        self.__systemStarted = False
        self.__vID = 0
        self.__isAlive = True
        self.__isTurretDetached = False
        self.__trackFashionSet = False
        self.__periodicTimerID = None
        self.__wasDeactivated = False
        return

    def prerequisites(self, typeDescriptor, vID, health, isCrewActive, isTurretDetached):
        self.__currentDamageState.update(health, isCrewActive, self.__isUnderWater)
        out = []
        out.append(typeDescriptor.type.camouflageExclusionMask)
        splineDesc = typeDescriptor.chassis['splineDesc']
        if splineDesc is not None:
            out.append(splineDesc['segmentModelLeft'])
            out.append(splineDesc['segmentModelRight'])
            if splineDesc['segment2ModelLeft'] is not None:
                out.append(splineDesc['segment2ModelLeft'])
            if splineDesc['segment2ModelRight'] is not None:
                out.append(splineDesc['segment2ModelRight'])
        customization = items.vehicles.g_cache.customization(typeDescriptor.type.customizationNationID)
        camouflageParams = self.__getCamouflageParams(typeDescriptor, vID)
        if camouflageParams is not None and customization is not None:
            camouflageId = camouflageParams[0]
            camouflageDesc = customization['camouflages'].get(camouflageId)
            if camouflageDesc is not None and camouflageDesc['texture'] != '':
                out.append(camouflageDesc['texture'])
                for tgDesc in (typeDescriptor.turret, typeDescriptor.gun):
                    exclMask = tgDesc.get('camouflageExclusionMask')
                    if exclMask is not None and exclMask != '':
                        out.append(exclMask)

        self.__vID = vID
        self.__typeDesc = typeDescriptor
        self.__isTurretDetached = isTurretDetached
        return out

    def setVehicle(self, vehicle):
        self.__vehicle = vehicle
        if self.__customEffectManager is not None:
            self.__customEffectManager.setVehicle(vehicle)
        if self.__crashedTracksCtrl is not None:
            self.__crashedTracksCtrl.setVehicle(vehicle)
        self.highlighter.setVehicle(vehicle)
        return

    def activate(self):
        if self.__activated or self.__vehicle is None:
            return
        else:
            if self.__currentDamageState.isCurrentModelDamaged:
                if self.__customEffectManager is not None:
                    self.__customEffectManager.destroy()
                    self.__customEffectManager = None
                if self.detailedEngineState is not None:
                    self.detailedEngineState.destroy()
                    self.detailedEngineState = None
            super(CompoundAppearance, self).activate()
            isPlayerVehicle = self.__vehicle.isPlayerVehicle
            isObserver = 'observer' in self.__typeDesc.type.tags
            player = BigWorld.player()
            self.__originalFilter = self.__vehicle.filter
            self.__createFilter()
            self.__vehicle.filter = self.__filter
            self.__vehicle.filter.enableNewPhysics(True)
            self.__vehicle.filter.enableStabilisedMatrix(isPlayerVehicle)
            self.__filter.isStrafing = self.__vehicle.isStrafing
            self.__filter.vehicleCollisionCallback = player.handleVehicleCollidedVehicle
            self.__compoundModel.isHighPriorityReflection = isPlayerVehicle
            self.__vehicleMatrixProv = self.__compoundModel.matrix
            if isPlayerVehicle:
                if player.inputHandler is not None:
                    player.inputHandler.addVehicleToCameraCollider(self.__vehicle)
                BigWorld.setSpeedTreeCollisionBody(self.__compoundModel.getBoundsForPart(TankPartIndexes.HULL))
            self.__linkCompound()
            self.__chassisShadowForwardDecal.attach(self.__typeDesc, self.__compoundModel)
            if not isObserver:
                self.__chassisOcclusionDecal.attach(self.__typeDesc, self.__compoundModel)
            self.__createStickers()
            if self.__currentDamageState.isCurrentModelDamaged:
                self.__attachStickers(items.vehicles.g_cache.commonConfig['miscParams']['damageStickerAlpha'], True)
            else:
                self.__startSystems()
                self.__attachStickers()
                self.setupGunMatrixTargets()
                if not isObserver:
                    self.__vehicle.filter.enableLagDetection(True)
            self.onModelChanged()
            if self.lodCalculator is not None:
                self.lodCalculator.setupPosition(DataLinks.linkMatrixTranslation(self.__compoundModel.matrix))
            if hasattr(self.filter, 'placingCompensationMatrix') and self.swingingAnimator is not None:
                self.swingingAnimator.placingCompensationMatrix = self.filter.placingCompensationMatrix
                self.swingingAnimator.worldMatrix = self.__compoundModel.matrix
            if self.__periodicTimerID is not None:
                BigWorld.cancelCallback(self.__periodicTimerID)
            self.__periodicTimerID = BigWorld.callback(_PERIODIC_TIME, self.__onPeriodicTimer)
            self.__activated = True
            if 'observer' in self.__vehicle.typeDescriptor.type.tags:
                self.__compoundModel.visible = False
            if self.__currentDamageState.isCurrentModelDamaged:
                if not self.__wasDeactivated:
                    if not self.__vehicle.isPlayerVehicle:
                        self.setupGunMatrixTargets()
                    else:
                        self.setupGunMatrixTargets(self.__vehicle.filter)
            return

    def deactivate(self, stopEffects = True):
        if not self.__activated:
            return
        else:
            self.__activated = False
            self.__wasDeactivated = True
            self.__stopSystems()
            super(CompoundAppearance, self).deactivate()
            self.__chassisOcclusionDecal.detach()
            self.__chassisShadowForwardDecal.detach()
            self.__vibrationsCtrl = None
            if self.__vehicle.isPlayerVehicle:
                BigWorld.setSpeedTreeCollisionBody(None)
            BigWorld.player().inputHandler.removeVehicleFromCameraCollider(self.__vehicle)
            self.__vehicle.filter.enableLagDetection(False)
            self.turretMatrix.setStaticTransform(self.turretMatrix)
            self.turretMatrix.target = None
            self.gunMatrix.setStaticTransform(self.gunMatrix)
            self.gunMatrix.target = None
            self.__vehicle.filter = self.__originalFilter
            self.__filter = None
            self.__originalFilter = None
            self.__vehicleStickers.detach()
            if stopEffects:
                self.__stopEffects()
                self.__boundEffects.stop()
            self.__vehicle.model = None
            self.__compoundModel.matrix = Math.Matrix()
            self.__vehicle = None
            self.__vehicleMatrixProv = None
            if self.__crashedTracksCtrl is not None:
                self.__crashedTracksCtrl.deactivate()
            return

    def __startSystems(self):
        if self.__trackScrollCtl is not None:
            self.__trackScrollCtl.activate()
            self.__trackScrollCtl.setData(self.__vehicle.filter, self.fashions.chassis)
        if self.__vehicle.isPlayerVehicle:
            self.delayCallback(_PERIODIC_TIME_ENGINE, self.__onPeriodicTimerEngine)
            self.highlighter.highlight(True)
        if self.detailedEngineState is not None:
            self.detailedEngineState.setVehicle(self.__vehicle)
            self.detailedEngineState.activate()
        if self.engineAudition is not None:
            self.engineAudition.vehicleFilter = self.filter
            self.engineAudition.activate()
            self.engineAudition.attachToModel(self.__compoundModel, self.__weaponEnergy)
        if self.__customEffectManager is not None:
            self.__customEffectManager.activate()
        if self.__vehicle.isAlive() and self.__vehicle.isPlayerVehicle:
            if self.__vibrationsCtrl is None:
                self.__vibrationsCtrl = VibrationControllersManager()
            if LightFx.LightManager.g_instance is not None and LightFx.LightManager.g_instance.isEnabled():
                self.__lightFxCtrl = LightFxControllersManager(self.__vehicle)
            if AuxiliaryFx.g_instance is not None:
                self.__auxiliaryFxCtrl = AuxiliaryFx.g_instance.createFxController(self.__vehicle)
        self.__systemStarted = True
        return

    def __stopSystems(self):
        if not self.__systemStarted:
            return
        else:
            self.__systemStarted = False
            if self.__periodicTimerID is not None:
                BigWorld.cancelCallback(self.__periodicTimerID)
                self.__periodicTimerID = None
            if self.detailedEngineState is not None:
                self.detailedEngineState.deactivate()
            if self.__vehicle.isPlayerVehicle:
                self.highlighter.highlight(False)
                self.stopCallback(self.__onPeriodicTimerEngine)
            if self.__trackScrollCtl is not None:
                self.__trackScrollCtl.deactivate()
                self.__trackScrollCtl.setData(None, None)
            if self.engineAudition is not None:
                self.engineAudition.deactivate()
            if self.trackCrashAudition is not None:
                self.trackCrashAudition.deactivate()
            if self.__customEffectManager is not None:
                self.__customEffectManager.deactivate()
            if self.engineAudition is not None:
                self.engineAudition.destroy()
            if self.__lightFxCtrl is not None:
                self.__lightFxCtrl.destroy()
                self.__lightFxCtrl = None
            if self.__auxiliaryFxCtrl is not None:
                self.__auxiliaryFxCtrl.destroy()
                self.__auxiliaryFxCtrl = None
            return

    def __destroySystems(self):
        if self.__periodicTimerID is not None:
            BigWorld.cancelCallback(self.__periodicTimerID)
            self.__periodicTimerID = None
        if self.customEffectManager is not None:
            self.customEffectManager.destroy()
            self.customEffectManager = None
        if self.__trackScrollCtl is not None:
            self.__trackScrollCtl.deactivate()
            self.__trackScrollCtl = None
        if self.engineAudition is not None:
            self.engineAudition.destroy()
            self.engineAudition = None
        if self.__vibrationsCtrl is not None:
            self.__vibrationsCtrl.destroy()
            self.__vibrationsCtrl = None
        if self.__lightFxCtrl is not None:
            self.__lightFxCtrl.destroy()
            self.__lightFxCtrl = None
        if self.__auxiliaryFxCtrl is not None:
            self.__auxiliaryFxCtrl.destroy()
            self.__auxiliaryFxCtrl = None
        if self.detailedEngineState is not None:
            self.detailedEngineState.destroy()
            self.detailedEngineState = None
        self.trackCrashAudition = None
        if self.__crashedTracksCtrl is not None:
            self.__crashedTracksCtrl.destroy()
            self.__crashedTracksCtrl = None
        return

    def destroy(self):
        self.__trackScrollCtl = None
        if self.__vehicle is not None:
            self.deactivate()
        self.__destroySystems()
        ComponentSystem.destroy(self)
        self.__typeDesc = None
        self.highlighter.destroy()
        if self.__vibrationsCtrl is not None:
            self.__vibrationsCtrl.destroy()
            self.__vibrationsCtrl = None
        if self.__lightFxCtrl is not None:
            self.__lightFxCtrl.destroy()
            self.__lightFxCtrl = None
        if self.__auxiliaryFxCtrl is not None:
            self.__auxiliaryFxCtrl.destroy()
            self.__auxiliaryFxCtrl = None
        if self.__boundEffects is not None:
            self.__boundEffects.destroy()
        self.__vehicleStickers = None
        self.onModelChanged = None
        if self.__crashedTracksCtrl is not None:
            self.__crashedTracksCtrl.destroy()
            self.__crashedTracksCtrl = None
        self.__chassisOcclusionDecal.destroy()
        self.__chassisOcclusionDecal = None
        self.__chassisShadowForwardDecal.destroy()
        self.__chassisShadowForwardDecal = None
        self.__compoundModel = None
        CallbackDelayer.destroy(self)
        return

    def __createFilter(self):
        self.__isPillbox = 'pillbox' in self.__typeDesc.type.tags
        if self.__isPillbox:
            self.__filter = BigWorld.WGPillboxFilter()
        else:
            self.__filter = BigWorld.WGVehicleFilter()
            self.__filter.vehicleWidth = self.__typeDesc.chassis['topRightCarryingPoint'][0] * 2
            self.__filter.maxMove = self.__typeDesc.physics['speedLimits'][0] * 2.0
            self.__filter.vehicleMinNormalY = self.__typeDesc.physics['minPlaneNormalY']
            for p1, p2, p3 in self.__typeDesc.physics['carryingTriangles']:
                self.__filter.addTriangle((p1[0], 0, p1[1]), (p2[0], 0, p2[1]), (p3[0], 0, p3[1]))

            fashion = self.__fashions[0]
            if fashion is not None:
                fashion.physicsInfo = self.__filter.physicsInfo
                fashion.movementInfo = self.__filter.movementInfo
            else:
                self.__trackFashionSet = False
            self.__filter.placingOnGround = self.__filter.placingOnGround if self.__trackFashionSet else False
        return

    def start(self, prereqs = None):
        if prereqs is None:
            self.__typeDesc.chassis['hitTester'].loadBspModel()
            self.__typeDesc.hull['hitTester'].loadBspModel()
            self.__typeDesc.turret['hitTester'].loadBspModel()
        for hitTester in self.__typeDesc.getHitTesters():
            hitTester.loadBspModel()

        self.__compoundModel = prereqs[self.__typeDesc.name]
        self.__boundEffects = bound_effects.ModelBoundEffects(self.__compoundModel)
        fashions = camouflages.prepareFashions(self.__typeDesc, self.__currentDamageState.isCurrentModelDamaged, self.__getCamouflageParams(self.__typeDesc, self.__vID)[0])
        if not self.__currentDamageState.isCurrentModelDamaged:
            self.__trackFashionSet = _setupVehicleFashion(fashions[0], self.__typeDesc)
        self.__compoundModel.setupFashions(fashions)
        fashions = camouflages.applyCamouflage(self.__typeDesc, fashions, self.__currentDamageState.isCurrentModelDamaged, self.__getCamouflageParams(self.__typeDesc, self.__vID)[0])
        fashions = camouflages.applyRepaint(self.__typeDesc, fashions)
        self.__setFashions(fashions, self.__isTurretDetached)
        self.__setupModels()
        if not VehicleDamageState.isDamagedModel(self.__currentDamageState.modelState):
            self.__splineTracks = setupSplineTracks(self.__fashion, self.__typeDesc, self.__compoundModel, prereqs)
        if self.__currentDamageState.effect is not None:
            self.__playEffect(self.__currentDamageState.effect, SpecialKeyPointNames.STATIC)
        if self.__currentDamageState.isCurrentModelDamaged:
            self.__trackScrollCtl = None
            self.__crashedTracksCtrl = None
        else:
            self.__crashedTracksCtrl = CrashedTrackController(self.__typeDesc, self.__fashion)
        return

    def showStickers(self, show):
        self.__vehicleStickers.show = show

    def updateTurretVisibility(self):
        self.__requestModelsRefresh()

    def changeVisibility(self, modelVisible):
        self.compoundModel.visible = modelVisible
        self.showStickers(modelVisible)
        if self.__crashedTracksCtrl is not None:
            self.__crashedTracksCtrl.setVisible(modelVisible)
        return

    def changeDrawPassVisibility(self, visibilityMask):
        colorPassEnabled = visibilityMask & BigWorld.ColorPassBit != 0
        self.compoundModel.visible = visibilityMask
        self.compoundModel.skipColorPass = not colorPassEnabled
        self.showStickers(colorPassEnabled)
        if self.__crashedTracksCtrl is not None:
            self.__crashedTracksCtrl.setVisible(visibilityMask)
        return

    def onVehicleHealthChanged(self):
        vehicle = self.__vehicle
        if not vehicle.isAlive():
            if vehicle.health > 0:
                self.changeEngineMode((0, 0))
        currentState = self.__currentDamageState
        previousState = currentState.state
        currentState.update(vehicle.health, vehicle.isCrewActive, self.__isUnderWater)
        if previousState != currentState.state:
            if currentState.effect is not None:
                self.__playEffect(currentState.effect)
            if vehicle.health <= 0:
                BigWorld.player().inputHandler.onVehicleDeath(vehicle, currentState.state == 'ammoBayExplosion')
                self.processVehicleDeath(currentState)
                self.__requestModelsRefresh()
        return

    @ComponentSystem.groupCall
    def processVehicleDeath(self, vehicleDamageState):
        pass

    def showAmmoBayEffect(self, mode, fireballVolume):
        if mode == constants.AMMOBAY_DESTRUCTION_MODE.POWDER_BURN_OFF:
            self.__playEffect('ammoBayBurnOff')
            return
        volumes = items.vehicles.g_cache.commonConfig['miscParams']['explosionCandleVolumes']
        candleIdx = 0
        for idx, volume in enumerate(volumes):
            if volume >= fireballVolume:
                break
            candleIdx = idx + 1

        if candleIdx > 0:
            self.__playEffect('explosionCandle%d' % candleIdx)
        else:
            self.__playEffect('explosion')

    def changeEngineMode(self, mode, forceSwinging = False):
        self.__engineMode = mode
        if self.detailedEngineState is not None:
            self.detailedEngineState.setMode(self.__engineMode[0])
        if self.__trackScrollCtl is not None:
            self.__trackScrollCtl.setMode(self.__engineMode)
        if BattleReplay.isPlaying() and BattleReplay.g_replayCtrl.isTimeWarpInProgress:
            return
        else:
            isOldPhysicsMode = self.__vehicle.physicsMode == VEHICLE_PHYSICS_MODE.STANDARD
            if isOldPhysicsMode and forceSwinging:
                flags = mode[1]
                prevFlags = self.__swingMoveFlags
                swingingAnimator = self.__swingingAnimator
                if swingingAnimator is not None:
                    moveMask = 3
                    rotMask = 12
                    if flags & moveMask ^ prevFlags & moveMask:
                        swingPeriod = 2.0
                        if flags & 1:
                            swingingAnimator.accelSwingingDirection = -1
                        elif flags & 2:
                            swingingAnimator.accelSwingingDirection = 1
                        else:
                            swingingAnimator.accelSwingingDirection = 0
                    elif not flags & moveMask and flags & rotMask ^ prevFlags & rotMask:
                        swingPeriod = 1.0
                        swingingAnimator.accelSwingingDirection = 0
                    else:
                        swingPeriod = 0.0
                    if swingPeriod > swingingAnimator.accelSwingingPeriod:
                        swingingAnimator.accelSwingingPeriod = swingPeriod
                self.__swingMoveFlags = flags
            return

    def stopSwinging(self):
        if self.__swingingAnimator is not None:
            self.__swingingAnimator.accelSwingingPeriod = 0.0
        return

    def removeDamageSticker(self, code):
        self.__vehicleStickers.delDamageSticker(code)

    def addDamageSticker(self, code, componentName, stickerID, segStart, segEnd):
        self.__vehicleStickers.addDamageSticker(code, componentName, stickerID, segStart, segEnd)

    def receiveShotImpulse(self, dir, impulse):
        if BattleReplay.isPlaying() and BattleReplay.g_replayCtrl.isTimeWarpInProgress:
            return
        else:
            if not VehicleDamageState.isDamagedModel(self.__currentDamageState.modelState):
                self.__swingingAnimator.receiveShotImpulse(dir, impulse)
                if self.__crashedTracksCtrl is not None:
                    self.__crashedTracksCtrl.receiveShotImpulse(dir, impulse)
            return

    def recoil(self):
        gunNode = self.compoundModel.node(TankNodeNames.GUN_INCLINATION)
        impulseDir = Math.Matrix(gunNode).applyVector(Math.Vector3(0, 0, -1))
        impulseValue = self.__typeDesc.gun['impulse']
        self.receiveShotImpulse(impulseDir, impulseValue)
        self.__gunRecoil.recoil()
        node = self.compoundModel.node('HP_gunFire')
        gunPos = Math.Matrix(node).translation
        BigWorld.player().inputHandler.onVehicleShaken(self.__vehicle, gunPos, impulseDir, self.__typeDesc.shot['shell']['caliber'], ShakeReason.OWN_SHOT_DELAYED)

    def addCrashedTrack(self, isLeft):
        if not self.__vehicle.isAlive():
            return
        else:
            if self.__crashedTracksCtrl is not None:
                self.__crashedTracksCtrl.addTrack(isLeft)
            if not self.__vehicle.isEnteringWorld and self.trackCrashAudition:
                self.trackCrashAudition.playCrashSound(isLeft)
            return

    def delCrashedTrack(self, isLeft):
        if self.__crashedTracksCtrl is not None:
            self.__crashedTracksCtrl.delTrack(isLeft)
        if not self.__vehicle.isEnteringWorld and self.trackCrashAudition and self.__vehicle.isPlayerVehicle:
            self.trackCrashAudition.playCrashSound(isLeft, True)
        return

    def __requestModelsRefresh(self):
        currentModelState = self.__currentDamageState.modelState
        assembler = model_assembler.prepareCompoundAssembler(self.__typeDesc, currentModelState, self.__vehicle.spaceID, self.__vehicle.isTurretDetached)
        BigWorld.loadResourceListBG([assembler], functools.partial(self.__onModelsRefresh, currentModelState))

    def __onModelsRefresh(self, modelState, resourceList):
        if BattleReplay.isFinished():
            return
        elif modelState != self.__currentDamageState.modelState:
            self.__requestModelsRefresh()
            return
        elif self.__vehicle is None:
            return
        else:
            vehicle = self.__vehicle
            newCompoundModel = resourceList[self.__typeDesc.name]
            self.deactivate(False)
            self.__compoundModel = newCompoundModel
            self.__isTurretDetached = vehicle.isTurretDetached
            if self.__currentDamageState.isCurrentModelDamaged:
                fashions = VehiclePartsTuple(None, None, None, None)
                self.swingingAnimator = None
                self.gunRecoil = None
                self.__setFashions(fashions, self.__isTurretDetached)
                self.__destroySystems()
                self.__trackFashionSet = False
            self.__setupModels()
            self.setVehicle(vehicle)
            self.activate()
            self.__reattachComponents(self.__compoundModel)
            lodLink = DataLinks.createFloatLink(self.lodCalculator, 'lodDistance')
            if not self.damageState.isCurrentModelDamaged:
                model_assembler.assembleRecoil(self, lodLink)
            model_assembler.setupTurretRotations(self)
            return

    def __setupModels(self):
        if not self.__currentDamageState.isCurrentModelDamaged:
            self.__gunFireNode = self.__compoundModel.node('HP_gunFire')
            self.__isAlive = True
            _, gunLength = self.__computeVehicleHeight()
            self.__weaponEnergy = gunLength * self.__typeDesc.shot['shell']['caliber']
            self.__setupHavok()
        else:
            self.__isAlive = False
            self.__gunFireNode = None
        if MAX_DISTANCE > 0:
            transform = self.__typeDesc.chassis['AODecals'][0]
            self.__attachSplodge(BigWorld.Splodge(transform, MAX_DISTANCE, self.__typeDesc.chassis['hullPosition'].y))
        return

    def __setupHavok(self):
        vDesc = self.__typeDesc
        node = self.compoundModel.node(TankPartNames.HULL)
        hkm = BigWorld.wg_createHKAttachment(node, vDesc.hull['hitTester'].getBspModel())
        if hkm is not None:
            node.attach(hkm)
        node = self.compoundModel.node(TankPartNames.TURRET)
        hkm = BigWorld.wg_createHKAttachment(node, vDesc.turret['hitTester'].getBspModel())
        if hkm is not None:
            node.attach(hkm)
        node = self.compoundModel.node(TankPartNames.CHASSIS)
        hkm = BigWorld.wg_createHKAttachment(node, vDesc.chassis['hitTester'].getBspModel())
        if hkm is not None:
            node.attach(hkm)
        node = self.compoundModel.node(TankPartNames.GUN)
        hkm = BigWorld.wg_createHKAttachment(node, vDesc.gun['hitTester'].getBspModel())
        if hkm is not None:
            node.attach(hkm)
        return

    def __reattachComponents(self, model):
        self.__boundEffects.reattachTo(model)
        if self.__effectsPlayer is not None:
            self.__effectsPlayer.reattachTo(model)
        if self.engineAudition is not None:
            self.engineAudition.attachToModel(model)
        return

    def __playEffect(self, kind, *modifs):
        self.__stopEffects()
        if kind == 'empty' or self.__vehicle is None:
            return
        else:
            enableDecal = True
            if not self.__isPillbox and kind in ('explosion', 'destruction'):
                filter = self.__vehicle.filter
                isFlying = filter.numLeftTrackContacts < 2 and filter.numRightTrackContacts < 2
                if isFlying:
                    enableDecal = False
            if self.isUnderwater:
                if kind not in ('submersionDeath',):
                    return
            effects = self.typeDescriptor.type.effects[kind]
            if not effects:
                return
            vehicle = self.__vehicle
            effects = random.choice(effects)
            self.__effectsPlayer = EffectsListPlayer(effects[1], effects[0], showShockWave=vehicle.isPlayerVehicle, showFlashBang=vehicle.isPlayerVehicle, isPlayer=vehicle.isPlayerVehicle, showDecal=enableDecal, start=vehicle.position + Math.Vector3(0.0, -1.0, 0.0), end=vehicle.position + Math.Vector3(0.0, 1.0, 0.0), entity_id=vehicle.id)
            self.__effectsPlayer.play(self.__compoundModel, *modifs)
            return

    __SPORT_ACTIONS_CAMOUFLAGES = {'ussr:T62A_sport': (95, 94),
     'usa:M24_Chaffee_GT': (82, 83)}

    def __getCamouflageParams(self, vDesc, vID):
        vehicleInfo = BigWorld.player().arena.vehicles.get(vID)
        if vehicleInfo is not None:
            camouflageIdPerTeam = VehicleAppearance.SPORT_ACTIONS_CAMOUFLAGES.get(vDesc.name)
            if camouflageIdPerTeam is not None:
                camouflageId = camouflageIdPerTeam[0] if vehicleInfo['team'] == 1 else camouflageIdPerTeam[1]
                return (camouflageId, time.time(), 100.0)
            camouflagePseudoname = vehicleInfo['events'].get('hunting', None)
            if camouflagePseudoname is not None:
                camouflIdsByNation = {0: {'black': 29,
                     'gold': 30,
                     'red': 31,
                     'silver': 32},
                 1: {'black': 25,
                     'gold': 26,
                     'red': 27,
                     'silver': 28},
                 2: {'black': 52,
                     'gold': 50,
                     'red': 51,
                     'silver': 53},
                 3: {'black': 48,
                     'gold': 46,
                     'red': 47,
                     'silver': 49},
                 4: {'black': 60,
                     'gold': 58,
                     'red': 59,
                     'silver': 61},
                 5: {'black': 56,
                     'gold': 54,
                     'red': 55,
                     'silver': 57},
                 6: {'black': 133,
                     'gold': 134,
                     'red': 135,
                     'silver': 136},
                 7: {'black': 141,
                     'gold': 142,
                     'red': 143,
                     'silver': 144},
                 8: {'black': 154,
                     'gold': 155,
                     'red': 156,
                     'silver': 157}}
                camouflIds = camouflIdsByNation.get(vDesc.type.customizationNationID)
                if camouflIds is not None:
                    ret = camouflIds.get(camouflagePseudoname)
                    if ret is not None:
                        return (ret, time.time(), 100.0)
        arenaType = BigWorld.player().arena.arenaType
        camouflageKind = arenaType.vehicleCamouflageKind
        return vDesc.camouflages[camouflageKind]

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

    def __calcIsUnderwater(self):
        if not self.__isInWater:
            return False
        turretOffs = self.__vehicle.typeDescriptor.chassis['hullPosition'] + self.__vehicle.typeDescriptor.hull['turretPositions'][0]
        turretOffsetMat = Math.Matrix()
        turretOffsetMat.setTranslate(turretOffs)
        turretJointMat = Math.Matrix(self.__vehicle.matrix)
        turretJointMat.preMultiply(turretOffsetMat)
        turretHeight = turretJointMat.translation.y - self.__vehicle.position.y
        return turretHeight < self.__waterHeight

    def __updateWaterStatus(self):
        vehiclePosition = self.__vehicle.position
        self.__waterHeight = BigWorld.wg_collideWater(vehiclePosition, vehiclePosition + Math.Vector3(0.0, 1.0, 0.0), False)
        self.__isInWater = self.__waterHeight != -1
        self.__isUnderWater = self.__calcIsUnderwater()
        wasSplashed = self.__splashedWater
        waterHitPoint = None
        if self.__isInWater:
            self.__splashedWater = True
            waterHitPoint = vehiclePosition + Math.Vector3(0.0, self.__waterHeight, 0.0)
        else:
            trPoint = self.__typeDesc.chassis['topRightCarryingPoint']
            cornerPoints = (Math.Vector3(trPoint.x, 0.0, trPoint.y),
             Math.Vector3(trPoint.x, 0.0, -trPoint.y),
             Math.Vector3(-trPoint.x, 0.0, -trPoint.y),
             Math.Vector3(-trPoint.x, 0.0, trPoint.y))
            vehMat = Math.Matrix(self.__vehicleMatrixProv)
            for cornerPoint in cornerPoints:
                pointToTest = vehMat.applyPoint(cornerPoint)
                dist = BigWorld.wg_collideWater(pointToTest, pointToTest + Math.Vector3(0.0, 1.0, 0.0))
                if dist != -1:
                    self.__splashedWater = True
                    waterHitPoint = pointToTest + Math.Vector3(0.0, dist, 0.0)
                    break

            self.__splashedWater = False
        if self.__splashedWater and not wasSplashed:
            lightVelocityThreshold = self.__typeDesc.type.collisionEffectVelocities['waterContact']
            heavyVelocityThreshold = self.__typeDesc.type.heavyCollisionEffectVelocities['waterContact']
            vehicleVelocity = abs(self.__speedInfo[0])
            if vehicleVelocity >= lightVelocityThreshold:
                collRes = BigWorld.wg_collideSegment(self.__vehicle.spaceID, waterHitPoint, waterHitPoint + (0.0, -_MIN_DEPTH_FOR_HEAVY_SPLASH, 0.0), 18, 8)
                deepEnough = collRes is None
                effectName = 'waterCollisionLight' if vehicleVelocity < heavyVelocityThreshold or not deepEnough else 'waterCollisionHeavy'
                self.__vehicle.showCollisionEffect(waterHitPoint, effectName, Math.Vector3(0.0, 1.0, 0.0))
        if self.__effectsPlayer is not None:
            if self.isUnderwater != (self.__currentDamageState.effect in ('submersionDeath',)):
                self.__stopEffects()
        return

    def updateTracksScroll(self, leftScroll, rightScroll):
        self.__leftTrackScroll = leftScroll
        self.__rightTrackScroll = rightScroll
        if self.__trackScrollCtl is not None:
            self.__trackScrollCtl.setExternal(leftScroll, rightScroll)
        return

    def __onPeriodicTimerEngine(self):
        if self.detailedEngineState is None or self.engineAudition is None:
            return
        else:
            self.detailedEngineState.refresh(_PERIODIC_TIME_ENGINE)
            self.engineAudition.tick()
            return _PERIODIC_TIME_ENGINE

    def __onPeriodicTimer(self):
        timeStamp = BigWorld.wg_getFrameTimestamp()
        if VehicleAppearance.frameTimeStamp >= timeStamp:
            self.__periodicTimerID = BigWorld.callback(0.0, self.__onPeriodicTimer)
            return
        else:
            VehicleAppearance.frameTimeStamp = timeStamp
            self.__periodicTimerID = BigWorld.callback(_PERIODIC_TIME, self.__onPeriodicTimer)
            if self.__isPillbox or self.__vehicle is None:
                return
            vehicle = self.__vehicle
            self.__speedInfo = vehicle.speedInfo.value
            if not self.__vehicle.isPlayerVehicle and self.detailedEngineState is not None:
                self.detailedEngineState.refresh(_PERIODIC_TIME)
            try:
                self.__updateVibrations()
                if self.__lightFxCtrl is not None:
                    self.__lightFxCtrl.update(vehicle)
                if self.__auxiliaryFxCtrl is not None:
                    self.__auxiliaryFxCtrl.update(vehicle)
                self.__updateWaterStatus()
                if not vehicle.isAlive():
                    return
                self.__distanceFromPlayer = (BigWorld.camera().position - vehicle.position).length
                extra = vehicle.typeDescriptor.extrasDict['fire']
                if extra.isRunningFor(vehicle):
                    extra.checkUnderwater(vehicle, self.isUnderwater)
                if self.__fashion is None:
                    return
                self.__updateCurrTerrainMatKinds()
                if not self.__vehicle.isPlayerVehicle:
                    self.engineAudition.tick()
                self.__updateEffectsLOD()
                vehicle.filter.placingOnGround = not self.__fashion.suspensionWorking
                if self.customEffectManager:
                    self.__customEffectManager.update()
                self.__vehicle.filter.placingOnGround = not self.__fashion.suspensionWorking
            except:
                LOG_CURRENT_EXCEPTION()

            return

    def __updateEffectsLOD(self):
        if self.customEffectManager:
            enableExhaust = self.__distanceFromPlayer <= _LOD_DISTANCE_EXHAUST
            enableTrails = self.__distanceFromPlayer <= _LOD_DISTANCE_TRAIL_PARTICLES and BigWorld.wg_isVehicleDustEnabled()
            self.__customEffectManager.enable(enableTrails, EffectSettings.SETTING_DUST)
            self.__customEffectManager.enable(enableExhaust, EffectSettings.SETTING_EXHAUST)

    def __updateCurrTerrainMatKinds(self):
        leftNode = self.compoundModel.node(TankNodeNames.TRACK_LEFT_MID)
        rightNode = self.compoundModel.node(TankNodeNames.TRACK_RIGHT_MID)
        testPoints = (Math.Matrix(leftNode).translation, Math.Matrix(rightNode).translation, self.__vehicle.position)
        isOnSoftTerrain = False
        for i in xrange(_MATKIND_COUNT):
            testPoint = testPoints[i]
            res = BigWorld.wg_collideSegment(self.__vehicle.spaceID, testPoint + Math.Vector3(0.0, 2.0, 0.0), testPoint + Math.Vector3(0.0, -2.0, 0.0), 18)
            matKind = res[2] if res is not None else 0
            self.__currTerrainMatKind[i] = matKind
            if not isOnSoftTerrain:
                groundStr = material_kinds.GROUND_STRENGTHS_BY_IDS.get(matKind)
                isOnSoftTerrain = groundStr == 'soft'

        if self.__vehicle.isPlayerVehicle and self.__wasOnSoftTerrain != isOnSoftTerrain:
            self.__wasOnSoftTerrain = isOnSoftTerrain
            if isOnSoftTerrain:
                TriggersManager.g_manager.activateTrigger(TRIGGER_TYPE.PLAYER_VEHICLE_ON_SOFT_TERRAIN)
            else:
                TriggersManager.g_manager.deactivateTrigger(TRIGGER_TYPE.PLAYER_VEHICLE_ON_SOFT_TERRAIN)
        self.__fashion.setCurrTerrainMatKinds(self.__currTerrainMatKind[0], self.__currTerrainMatKind[1])
        return

    def switchFireVibrations(self, bStart):
        if self.__vibrationsCtrl is not None:
            self.__vibrationsCtrl.switchFireVibrations(bStart)
        return

    def executeHitVibrations(self, hitEffectCode):
        if self.__vibrationsCtrl is not None:
            self.__vibrationsCtrl.executeHitVibrations(hitEffectCode)
        return

    def executeRammingVibrations(self, matKind = None):
        if self.__vibrationsCtrl is not None:
            self.__vibrationsCtrl.executeRammingVibrations(self.__vehicle.getSpeed(), matKind)
        return

    def executeShootingVibrations(self, caliber):
        if self.__vibrationsCtrl is not None:
            self.__vibrationsCtrl.executeShootingVibrations(caliber)
        return

    def executeCriticalHitVibrations(self, vehicle, extrasName):
        if self.__vibrationsCtrl is not None:
            self.__vibrationsCtrl.executeCriticalHitVibrations(vehicle, extrasName)
        return

    def deviceStateChanged(self, deviceName, state):
        if self.detailedEngineState is not None and deviceName == 'engine':
            self.detailedEngineState.deviceStateChanged(state)
        return

    def __updateVibrations(self):
        if self.__vibrationsCtrl is None:
            return
        else:
            vehicle = self.__vehicle
            if self.__crashedTracksCtrl is not None:
                crashedTrackCtrl = self.__crashedTracksCtrl
                self.__vibrationsCtrl.update(vehicle, crashedTrackCtrl.isLeftTrackBroken(), crashedTrackCtrl.isRightTrackBroken())
            return

    def __linkCompound(self):
        vehicle = self.__vehicle
        vehicle.model = None
        vehicle.model = self.__compoundModel
        vehicleMatrix = vehicle.matrix
        self.__compoundModel.matrix = vehicleMatrix
        return

    def __createStickers(self):
        if self.__vehicleStickers is not None:
            return
        else:
            insigniaRank = self.__vehicle.publicInfo['marksOnGun']
            self.__vehicleStickers = VehicleStickers(self.__typeDesc, insigniaRank)
            clanID = BigWorld.player().arena.vehicles[self.__vehicle.id]['clanDBID']
            self.__vehicleStickers.setClanID(clanID)
            return

    def __attachStickers(self, alpha = 1.0, emblemsOnly = False):
        try:
            self.__vehicleStickers.alpha = alpha
            self.__vehicleStickers.attach(self.compoundModel, self.__currentDamageState.isCurrentModelDamaged, not emblemsOnly)
        except:
            LOG_CURRENT_EXCEPTION()

    def __attachSplodge(self, splodge):
        node = self.__compoundModel.node(TankPartNames.HULL)
        if splodge is not None and self.__splodge is None:
            self.__splodge = splodge
            node.attach(splodge)
        return

    def __disableStipple(self):
        self.compoundModel.stipple = False

    def __computeVehicleHeight(self):
        desc = self.__typeDesc
        turretBBox = desc.turret['hitTester'].bbox
        gunBBox = desc.gun['hitTester'].bbox
        hullBBox = desc.hull['hitTester'].bbox
        hullTopY = desc.chassis['hullPosition'][1] + hullBBox[1][1]
        turretTopY = desc.chassis['hullPosition'][1] + desc.hull['turretPositions'][0][1] + turretBBox[1][1]
        gunTopY = desc.chassis['hullPosition'][1] + desc.hull['turretPositions'][0][1] + desc.turret['gunPosition'][1] + gunBBox[1][1]
        return (max(hullTopY, max(turretTopY, gunTopY)), math.fabs(gunBBox[1][2] - gunBBox[0][2]))

    def setupGunMatrixTargets(self, target = None):
        if target is None:
            target = self.__filter
        self.turretMatrix.target = target.turretMatrix
        self.gunMatrix.target = target.gunMatrix
        return

    def assembleStipple(self):
        compound = self.compoundModel
        compound.matrix = Math.Matrix(compound.matrix)
        hullNode = compound.node(TankPartNames.HULL)
        compound.node(TankPartNames.HULL, hullNode.localMatrix)
        turretRotation = compound.node(TankPartNames.TURRET)
        if turretRotation is not None:
            compound.node(TankPartNames.TURRET, turretRotation.localMatrix)
        gunInclination = compound.node(TankNodeNames.GUN_INCLINATION)
        if gunInclination is not None:
            compound.node(TankNodeNames.GUN_INCLINATION, gunInclination.localMatrix)
        gunRecoil = compound.node(TankNodeNames.GUN_RECOIL)
        if gunRecoil is not None:
            compound.node(TankNodeNames.GUN_RECOIL, gunRecoil.localMatrix)
        self.fashions = VehiclePartsTuple(None, None, None, None)
        return
예제 #36
0
class _CTFResourcePointModel():

    def __init__(self, pointModelName, effectsSectionName):
        self.__modelFile = None
        self.__model = None
        self.__effectsTimeLine = None
        self.__effectsPlayer = None
        self.__loadTask = None
        self.__hideListener = None
        g_ctfManager.registerResourcePointModel(self)
        modelParams = _g_ctfConfig.readModelParams(pointModelName)
        if modelParams is not None:
            self.__modelFile = modelParams.get('file')
        if self.__modelFile is None:
            LOG_ERROR('%s: can\'t find the "%s" model.' % (_g_ctfConfig.name, pointModelName))
        effectsSection = _g_ctfConfig.readFirstLvlSection(effectsSectionName)
        if effectsSection is not None:
            self.__effectsTimeLine = effectsFromSection(effectsSection)
        return

    def __del__(self):
        self.__hideListener = None
        if self.__loadTask is not None:
            _g_resLoader.stopLoadTask(self.__loadTask)
            self.__loadTask = None
        g_ctfManager.unregisterResourcePointModel(self)
        if self.__effectsPlayer is not None:
            self.stopEffect()
            self.__effectsPlayer = None
        self.__effectsTimeLine = None
        if self.__model is not None:
            BigWorld.delModel(self.__model)
            self.__model = None
        self.__modelFile = None
        return

    def _createPoint(self):
        if g_ctfManager.isNeedHideAll:
            return
        else:
            raise self.__modelFile is not None or AssertionError
            self.__loadTask = _g_resLoader.startLoadTask((self.__modelFile,), self.__onModelLoaded)
            return

    def __onModelLoaded(self, resourceRefs):
        if resourceRefs.failedIDs:
            LOG_ERROR('Failed to load model %s' % (resourceRefs.failedIDs,))
        else:
            model = resourceRefs[self.__modelFile]
            if not model is not None:
                raise AssertionError
                model.position = self.position
                roll, pitch, yaw = self.direction
                model.rotate(roll, (0.0, 0.0, 1.0))
                model.rotate(pitch, (1.0, 0.0, 0.0))
                model.rotate(yaw, (0.0, 1.0, 0.0))
                BigWorld.addModel(model, BigWorld.player().spaceID)
                BigWorld.wg_applyOverlayToModel(model, False)
                self.__model = model
                g_ctfManager.updateRegisteredResourcePointModel(self)
                g_ctfManager.isNeedHideAll and self.__hideResPointFlag()
            else:
                self.__hideListener = _GlobalHideListener(self.__hideResPointFlag)
        return

    def __hideResPointFlag(self):
        if self.__model is not None:
            self.__model.visible = False
        self.stopEffect()
        return

    def playEffect(self):
        if self.__effectsPlayer is not None:
            return
        elif self.__model is None:
            return
        else:
            if self.__effectsTimeLine is not None:
                self.__effectsPlayer = EffectsListPlayer(self.__effectsTimeLine.effectsList, self.__effectsTimeLine.keyPoints)
                self.__effectsPlayer.play(self.__model)
            return

    def stopEffect(self):
        if self.__effectsPlayer is None:
            return
        else:
            self.__effectsPlayer.stop()
            self.__effectsPlayer = None
            return
class DestructibleEntityState(ScriptGameObject):
    guiNode = property(lambda self: self.__guiNode)
    damageStickers = property(lambda self: self.__damageStickers)
    collisionComponent = ComponentDescriptor()
    name = property(lambda self: self.__stateName)

    def __init__(self, stateName, stateProperties, entityId, trigger, spaceID):
        ScriptGameObject.__init__(self, spaceID, 'DestructibleEntityState')
        self.__entityId = entityId
        self.__stateName = stateName
        self.__stateProperties = stateProperties
        self.__guiNode = None
        self.__active = False
        self.__visualModel = None
        self.__damageStickers = dict()
        self.__effectsPlayer = None
        self.__trigger = trigger
        return

    def isTriggered(self):
        return self.__trigger() and not self.__active

    def reduceSegmentLength(self, hitCompIndx, segStart, segEnd):
        hitDist = self.collisionComponent.collideLocal(hitCompIndx, segStart,
                                                       segEnd)
        if hitDist is None:
            return (segStart, segEnd)
        else:
            rayDir = Math.Vector3(segEnd) - Math.Vector3(segStart)
            rayDir.normalise()
            hitPoint = segStart + rayDir * hitDist
            return (hitPoint - rayDir / 2.0 * COLLISION_SEGMENT_LENGTH,
                    hitPoint + rayDir / 2.0 * COLLISION_SEGMENT_LENGTH)

    def prereqs(self, spaceId):
        visualModel = BigWorld.CompoundAssembler(
            self.__stateName + ASSEMBLER_NAME_SUFFIXES.VISUAL, spaceId)
        bspModels = []
        for componentIdx, (componentId, component) in enumerate(
                self.__stateProperties.components.iteritems()):
            if componentIdx == 0:
                visualModel.addRootPart(component.visualModel, 'root')
            else:
                visualModel.emplacePart(component.visualModel, 'root',
                                        componentId)
            bspModels.append((componentIdx, component.physicsModel))

        collisionAssembler = BigWorld.CollisionAssembler(
            tuple(bspModels), self.spaceID)
        collisionAssembler.name = self.__stateName + ASSEMBLER_NAME_SUFFIXES.PHYSICS
        return [visualModel, collisionAssembler]

    def onResourcesLoaded(self, prereqs):
        assemblerName = self.__stateName + ASSEMBLER_NAME_SUFFIXES.PHYSICS
        if assemblerName not in prereqs.failedIDs:
            self.collisionComponent = self.createComponent(
                BigWorld.CollisionComponent, prereqs[assemblerName])
        assemblerName = self.__stateName + ASSEMBLER_NAME_SUFFIXES.VISUAL
        if assemblerName not in prereqs.failedIDs:
            self.__visualModel = prereqs[assemblerName]
            for componentIdx, component in enumerate(
                    self.__stateProperties.components.itervalues()):
                self.__visualModel.setPartProperties(
                    componentIdx,
                    int(component.destructible) <<
                    PART_PROPERTIES.HIGHLIGHTABLE)
                link = self.__visualModel.getPartGeometryLink(componentIdx)
                self.__damageStickers[componentIdx] = DestructibleStickers(
                    link, self.__visualModel.node('root'))

            nodeName = next(
                (comp.guiNode
                 for comp in self.__stateProperties.components.itervalues()
                 if comp.guiNode is not None), None)
            if nodeName is not None:
                self.__guiNode = self.__visualModel.node(nodeName)
        return

    def activate(self, matrix):
        payload = []
        for componentIdx, _ in enumerate(self.__stateProperties.components):
            payload.append((componentIdx, self.__visualModel.node('root')))

        self.collisionComponent.connect(self.__entityId,
                                        ColliderTypes.VEHICLE_COLLIDER,
                                        tuple(payload))
        self.__visualModel.matrix = matrix
        self.__playEffect(self.__stateProperties.effect, self.__visualModel)
        self.__active = True
        super(DestructibleEntityState, self).activate()
        return self.__visualModel

    def deactivate(self):
        for componentIdx in range(len(self.__stateProperties.components)):
            self.collisionComponent.removeAttachment(componentIdx)

        super(DestructibleEntityState, self).deactivate()
        self.__stopEffect()
        self.__active = False

    def destroy(self):
        super(DestructibleEntityState, self).destroy()
        self.__effectsPlayer = None
        self.__damageStickers = None
        self.__visualModel = None
        self.__guiNode = None
        self.__stateProperties = None
        self.__stateName = None
        return

    def collideAllWorld(self, startPoint, endPoint):
        return self.__collisionComponent.collideAllWorld(
            startPoint,
            endPoint) if self.__collisionComponent is not None else None

    def isDestructibleComponent(self, componentID):
        component = next((c for cIDx, c in enumerate(
            self.__stateProperties.components.itervalues())
                          if cIDx == componentID), None)
        return component.destructible if component is not None else False

    def __playEffect(self, effectName, model):
        if self.__effectsPlayer is not None or None in (model, effectName):
            return
        else:
            effectsSection = destructible_entities.g_destructibleEntitiesCache.getDestroyEffectList(
                effectName)
            if effectsSection is None:
                return
            effects = effectsFromSection(effectsSection)
            if effects is None:
                return
            fakeModel = helpers.newFakeModel()
            BigWorld.player().addModel(fakeModel)
            tmpMatrix = Math.Matrix(self.__visualModel.matrix)
            fakeModel.position = tmpMatrix.translation
            self.__effectsPlayer = EffectsListPlayer(effects.effectsList,
                                                     effects.keyPoints)
            self.__effectsPlayer.play(fakeModel, None)
            return

    def __stopEffect(self):
        if self.__effectsPlayer is None:
            return
        else:
            self.__effectsPlayer.stop()
            self.__effectsPlayer = None
            return
예제 #38
0
 def __playStateEffect(self, startKeyPoint=SpecialKeyPointNames.START):
     self.__stopStateEffects()
     effectName = _TurretDetachmentEffects.__EFFECT_NAMES[self.__state]
     stages, effectsList, _ = self.__detachmentEffectsDesc[effectName]
     self.__stateEffectListPlayer = EffectsListPlayer(effectsList, stages)
     self.__stateEffectListPlayer.play(self.__turretModel, startKeyPoint)
예제 #39
0
class _TurretDetachmentEffects(Component):
    class State:
        FLYING = 0
        ON_GROUND = 1

    __EFFECT_NAMES = {
        State.FLYING: 'flight',
        State.ON_GROUND: 'flamingOnGround'
    }
    _MAX_COLLISION_ENERGY = 98.10000000000001
    _MIN_COLLISION_ENERGY = _MIN_COLLISION_SPEED**2 * 0.5
    _MIN_NORMALIZED_ENERGY = 0.1
    _DROP_ENERGY_PARAM = 'RTPC_ext_drop_energy'

    def __init__(self, turretModel, detachmentEffectsDesc, onGround):
        self.__turretModel = turretModel
        self.__detachmentEffectsDesc = detachmentEffectsDesc
        self.__stateEffectListPlayer = None
        self.__pullEffectListPlayer = None
        startKeyPoint = SpecialKeyPointNames.START
        if onGround:
            self.__state = self.State.ON_GROUND
            startKeyPoint = SpecialKeyPointNames.STATIC
        else:
            self.__state = self.State.FLYING
        self.__playStateEffect(startKeyPoint)
        return

    def destroy(self):
        self.stopEffects()

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

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

    def stopEffects(self):
        self.__stopStateEffects()
        self.__stopPullEffects()

    def notifyAboutCollision(self, energy, collisionPoint, effectMaterialIdx,
                             groundEffect, underWater):
        if groundEffect:
            stages, effectsList, _ = self.__detachmentEffectsDesc['collision'][
                effectMaterialIdx]
            normalizedEnergy = self.__normalizeEnergy(energy)
            dropEnergyParam = SoundStartParam(
                _TurretDetachmentEffects._DROP_ENERGY_PARAM, normalizedEnergy)
            BigWorld.player().terrainEffects.addNew(
                collisionPoint,
                effectsList,
                stages,
                None,
                soundParams=[dropEnergyParam])
        if self.__state != self.State.ON_GROUND:
            self.__state = self.State.ON_GROUND
            if not underWater:
                self.__playStateEffect()
        return

    def notifyAboutBeingPulled(self, isPulled, effectMaterialIdx):
        if isPulled:
            if self.__pullEffectListPlayer is None or self.__pullEffectListPlayer.effectMaterialIdx != effectMaterialIdx:
                self.__playPullEffect(effectMaterialIdx)
        else:
            self.__stopPullEffects()
        return

    def __playPullEffect(self, effectMaterialIdx):
        self.__stopPullEffects()
        result = self.__detachmentEffectsDesc['pull'].get(
            effectMaterialIdx, None)
        if result is None:
            return
        else:
            stages, effectsList, _ = result
            self.__pullEffectListPlayer = EffectsListPlayer(
                effectsList, stages)
            self.__pullEffectListPlayer.play(self.__turretModel,
                                             SpecialKeyPointNames.START)
            self.__pullEffectListPlayer.effectMaterialIdx = effectMaterialIdx
            return

    def __playStateEffect(self, startKeyPoint=SpecialKeyPointNames.START):
        self.__stopStateEffects()
        effectName = _TurretDetachmentEffects.__EFFECT_NAMES[self.__state]
        stages, effectsList, _ = self.__detachmentEffectsDesc[effectName]
        self.__stateEffectListPlayer = EffectsListPlayer(effectsList, stages)
        self.__stateEffectListPlayer.play(self.__turretModel, startKeyPoint)

    def __normalizeEnergy(self, energy):
        minBound, maxBound = _TurretDetachmentEffects._MIN_COLLISION_ENERGY, _TurretDetachmentEffects._MAX_COLLISION_ENERGY
        clampedEnergy = mathUtils.clamp(minBound, maxBound, energy)
        t = (clampedEnergy - minBound) / (maxBound - minBound)
        return mathUtils.lerp(_TurretDetachmentEffects._MIN_NORMALIZED_ENERGY,
                              1.0, t)