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
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