class ParachuteCargo(ScriptGameObject, CallbackDelayer): model = ComponentDescriptorTyped(ModelComponent) landingAnimation = ComponentDescriptorTyped(SequenceComponent) descendSimulator = ComponentDescriptor() LANDING_TRIGGER = 'Landed' LANDING_ANIMATION_TRIGGER_OFFSET = -0.3 def __init__(self, yaw, dropPoint, landingPosition, descendTime): ScriptGameObject.__init__(self, BigWorld.player().spaceID) CallbackDelayer.__init__(self) self.descendSimulator = DescendSimulator(yaw, dropPoint, landingPosition, descendTime) self.__descendTime = descendTime self.__dropPoint = dropPoint def activate(self): ScriptGameObject.activate(self) self.model.compoundModel.position = self.__dropPoint self.model.compoundModel.matrix = self.descendSimulator.matrix self.landingAnimation.bindToCompound(self.model.compoundModel) self.landingAnimation.start() self.delayCallback( self.__descendTime + self.LANDING_ANIMATION_TRIGGER_OFFSET, self.__animateLanding) def deactivate(self): super(ParachuteCargo, self).deactivate() if self.landingAnimation is not None: self.landingAnimation.stop() self.landingAnimation.unbind() return def destroy(self): ScriptGameObject.destroy(self) CallbackDelayer.destroy(self) def __animateLanding(self): if self.landingAnimation is not None: self.landingAnimation.setTrigger(self.LANDING_TRIGGER) return
class HangarVehicleAppearance(ScriptGameObject): __ROOT_NODE_NAME = 'V' itemsCache = dependency.descriptor(IItemsCache) itemsFactory = dependency.descriptor(IGuiItemsFactory) settingsCore = dependency.descriptor(ISettingsCore) turretAndGunAngles = dependency.descriptor(ITurretAndGunAngles) customizationService = dependency.descriptor(ICustomizationService) wheelsAnimator = ComponentDescriptor() trackNodesAnimator = ComponentDescriptor() collisions = ComponentDescriptor() shadowManager = ComponentDescriptor() dirtComponent = ComponentDescriptor() c11nComponent = ComponentDescriptor() tracks = ComponentDescriptor() collisionObstaclesCollector = ComponentDescriptor() tessellationCollisionSensor = ComponentDescriptor() flagComponent = ComponentDescriptor() @property def compoundModel(self): return self.__vEntity.model if self.__vEntity else None @property def id(self): return self.__vEntity.id fashion = property(lambda self: self.__fashions[0]) @property def filter(self): return None isVehicleDestroyed = property(lambda self: self.__isVehicleDestroyed) def __init__(self, spaceId, vEntity): ScriptGameObject.__init__(self, vEntity.spaceID) self.__loadState = _LoadStateNotifier() self.__curBuildInd = 0 self.__vDesc = None self.__vState = None size = len(TankPartNames.ALL) self.__fashions = VehiclePartsTuple(*([None] * size)) self.__repaintHandlers = [None] * size self.__camoHandlers = [None] * size self.__projectionDecalsHandlers = [None] * size self.__projectionDecalsUpdater = None self.__spaceId = spaceId self.__vEntity = weakref.proxy(vEntity) self.__onLoadedCallback = None self.__onLoadedAfterRefreshCallback = None self.__vehicleStickers = None self.__isVehicleDestroyed = False self.__outfit = None self.__staticTurretYaw = 0.0 self.__staticGunPitch = 0.0 self.__anchorsHelpers = None self.__anchorsParams = None self.__attachments = [] self.__modelAnimators = [] self.shadowManager = None cfg = hangarCFG() self.__currentEmblemsAlpha = cfg['emblems_alpha_undamaged'] self.__showMarksOnGun = self.settingsCore.getSetting('showMarksOnGun') self.settingsCore.onSettingsChanged += self.__onSettingsChanged self.itemsCache.onSyncCompleted += self.__onItemsCacheSyncCompleted g_eventBus.addListener(CameraRelatedEvents.CAMERA_ENTITY_UPDATED, self.__handleEntityUpdated) g_currentVehicle.onChanged += self.__onVehicleChanged return def recreate(self, vDesc, vState=None, callback=None, outfit=None): self.__onLoadedCallback = callback self.__reload(vDesc, vState or self.__vState, outfit or self._getActiveOutfit(vDesc)) def remove(self): self.__clearModelAnimators() self.__loadState.unload() self.__vDesc = None self.__vState = None self.__isVehicleDestroyed = False self.__vEntity.model = None if self.shadowManager is not None: self.shadowManager.updatePlayerTarget(None) if self.collisions: BigWorld.removeCameraCollider(self.collisions.getColliderID()) self.collisions = None return def refresh(self, outfit=None, callback=None): if self.__loadState.isLoaded and self.__vDesc: if callback is not None: self.__onLoadedAfterRefreshCallback = callback self.__reload(self.__vDesc, self.__vState, outfit or self.__outfit) return def destroy(self): if self.fashion is not None: self.fashion.removePhysicalTracks() if self.shadowManager is not None: self.shadowManager.updatePlayerTarget(None) self.__clearModelAnimators() ScriptGameObject.deactivate(self) ScriptGameObject.destroy(self) self.__vDesc = None self.__vState = None self.__loadState.unload() self.__loadState.destroy() self.__loadState = None self.__curBuildInd = 0 self.__vEntity = None self.__onLoadedCallback = None self.__onLoadedAfterRefreshCallback = None self.turretRotator = None self.settingsCore.onSettingsChanged -= self.__onSettingsChanged self.itemsCache.onSyncCompleted -= self.__onItemsCacheSyncCompleted g_eventBus.removeListener(CameraRelatedEvents.CAMERA_ENTITY_UPDATED, self.__handleEntityUpdated) g_currentVehicle.onChanged -= self.__onVehicleChanged return @property def loadState(self): return self.__loadState @property def fakeShadowDefinedInHullTexture(self): return self.__vDesc.hull.hangarShadowTexture if self.__vDesc else None def isLoaded(self): return self.__loadState.isLoaded def recreateRequired(self, newOutfit): shouldUpdateModelsSet = self.__outfit.modelsSet != newOutfit.modelsSet shouldUpdateAttachments = not self.__outfit.attachments.isEqual( newOutfit.attachments) return shouldUpdateModelsSet or shouldUpdateAttachments def computeVehicleHeight(self): gunLength = 0.0 height = 0.0 if self.collisions is not None: desc = self.__vDesc hullBB = self.collisions.getBoundingBox( TankPartNames.getIdx(TankPartNames.HULL)) turretBB = self.collisions.getBoundingBox( TankPartNames.getIdx(TankPartNames.TURRET)) gunBB = self.collisions.getBoundingBox( TankPartNames.getIdx(TankPartNames.GUN)) hullTopY = desc.chassis.hullPosition[1] + hullBB[1][1] turretTopY = desc.chassis.hullPosition[ 1] + desc.hull.turretPositions[0][1] + turretBB[1][1] gunTopY = desc.chassis.hullPosition[1] + desc.hull.turretPositions[ 0][1] + desc.turret.gunPosition[1] + gunBB[1][1] gunLength = math.fabs(gunBB[1][2] - gunBB[0][2]) height = max(hullTopY, max(turretTopY, gunTopY)) return (height, gunLength) def computeVehicleLength(self): vehicleLength = 0.0 if self.collisions is not None: hullBB = self.collisions.getBoundingBox( TankPartNames.getIdx(TankPartNames.HULL)) vehicleLength = abs(hullBB[1][2] - hullBB[0][2]) return vehicleLength def computeFullVehicleLength(self): hullBB = Math.Matrix( self.__vEntity.model.getBoundsForPart(TankPartIndexes.HULL)) return hullBB.applyVector(Math.Vector3(0.0, 0.0, 1.0)).length def _getTurretYaw(self): return self.turretAndGunAngles.getTurretYaw() def _getGunPitch(self): return self.turretAndGunAngles.getGunPitch() def __reload(self, vDesc, vState, outfit): self.__clearModelAnimators() self.__loadState.unload() if self.fashion is not None: self.fashion.removePhysicalTracks() ScriptGameObject.deactivate(self) self.tracks = None self.collisionObstaclesCollector = None self.tessellationCollisionSensor = None self.shadowManager = VehicleShadowManager() self.shadowManager.updatePlayerTarget(None) self.__outfit = outfit self.__startBuild(vDesc, vState) return def __startBuild(self, vDesc, vState): self.__curBuildInd += 1 self.__vState = vState self.__resources = {} self.__vehicleStickers = None cfg = hangarCFG() if vState == 'undamaged': self.__currentEmblemsAlpha = cfg['emblems_alpha_undamaged'] self.__isVehicleDestroyed = False else: self.__currentEmblemsAlpha = cfg['emblems_alpha_damaged'] self.__isVehicleDestroyed = True self.__vDesc = vDesc resources = camouflages.getCamoPrereqs(self.__outfit, vDesc) if not self.__isVehicleDestroyed: self.__attachments = camouflages.getAttachments( self.__outfit, vDesc) modelsSet = self.__outfit.modelsSet splineDesc = vDesc.chassis.splineDesc if splineDesc is not None: resources.append(splineDesc.segmentModelLeft(modelsSet)) resources.append(splineDesc.segmentModelRight(modelsSet)) if splineDesc.leftDesc is not None: resources.append(splineDesc.leftDesc) if splineDesc.rightDesc is not None: resources.append(splineDesc.rightDesc) segment2ModelLeft = splineDesc.segment2ModelLeft(modelsSet) if segment2ModelLeft is not None: resources.append(segment2ModelLeft) segment2ModelRight = splineDesc.segment2ModelRight(modelsSet) if segment2ModelRight is not None: resources.append(segment2ModelRight) from vehicle_systems import model_assembler resources.append( model_assembler.prepareCompoundAssembler( self.__vDesc, ModelsSetParams(modelsSet, self.__vState, self.__attachments), self.__spaceId)) g_eventBus.handleEvent(CameraRelatedEvents( CameraRelatedEvents.VEHICLE_LOADING, ctx={ 'started': True, 'vEntityId': self.__vEntity.id, 'intCD': self.__vDesc.type.compactDescr }), scope=EVENT_BUS_SCOPE.DEFAULT) cfg = hangarCFG() gunScale = Math.Vector3(1.0, 1.0, 1.1) capsuleScale = Math.Vector3(1.5, 1.5, 1.5) loadedGunScale = cfg.get('cam_capsule_gun_scale', gunScale) if loadedGunScale is not None: gunScale = loadedGunScale loadedCapsuleScale = cfg.get('cam_capsule_scale', capsuleScale) if loadedCapsuleScale is not None: capsuleScale = loadedCapsuleScale bspModels = ((TankPartNames.getIdx(TankPartNames.CHASSIS), vDesc.chassis.hitTester.bspModelName), (TankPartNames.getIdx(TankPartNames.HULL), vDesc.hull.hitTester.bspModelName), (TankPartNames.getIdx(TankPartNames.TURRET), vDesc.turret.hitTester.bspModelName), (TankPartNames.getIdx(TankPartNames.GUN), vDesc.gun.hitTester.bspModelName), (TankPartNames.getIdx(TankPartNames.GUN) + 1, vDesc.hull.hitTester.bspModelName, capsuleScale), (TankPartNames.getIdx(TankPartNames.GUN) + 2, vDesc.turret.hitTester.bspModelName, capsuleScale), (TankPartNames.getIdx(TankPartNames.GUN) + 3, vDesc.gun.hitTester.bspModelName, gunScale)) collisionAssembler = BigWorld.CollisionAssembler( bspModels, self.__spaceId) resources.append(collisionAssembler) physicalTracksBuilders = vDesc.chassis.physicalTracks for name, builders in physicalTracksBuilders.iteritems(): for index, builder in enumerate(builders): resources.append( builder.createLoader( self.__spaceId, '{0}{1}PhysicalTrack'.format(name, index), modelsSet)) BigWorld.loadResourceListBG( tuple(resources), makeCallbackWeak(self.__onResourcesLoaded, self.__curBuildInd)) return def __onResourcesLoaded(self, buildInd, resourceRefs): if not self.__vDesc: self.__fireResourcesLoadedEvent() return if buildInd != self.__curBuildInd: return failedIDs = resourceRefs.failedIDs resources = self.__resources succesLoaded = True for resID, resource in resourceRefs.items(): if resID not in failedIDs: resources[resID] = resource _logger.error('Could not load %s', resID) succesLoaded = False if self.collisions: BigWorld.removeCameraCollider(self.collisions.getColliderID()) self.collisions = resourceRefs['collisionAssembler'] if succesLoaded: self.__setupModel(buildInd) self.turretRotator = SimpleTurretRotator( self.compoundModel, easingCls=math_utils.Easing.squareEasing) self.__applyAttachmentsVisibility() self.__fireResourcesLoadedEvent() super(HangarVehicleAppearance, self).activate() def __fireResourcesLoadedEvent(self): compDescr = self.__vDesc.type.compactDescr if self.__vDesc is not None else None g_eventBus.handleEvent(CameraRelatedEvents( CameraRelatedEvents.VEHICLE_LOADING, ctx={ 'started': False, 'vEntityId': self.__vEntity.id, 'intCD': compDescr }), scope=EVENT_BUS_SCOPE.DEFAULT) return def __onAnimatorsLoaded(self, buildInd, outfit, resourceRefs): if not self.__vDesc: return if buildInd != self.__curBuildInd: return self.__clearModelAnimators() self.__modelAnimators = camouflages.getModelAnimators( outfit, self.__vDesc, self.__spaceId, resourceRefs, self.compoundModel) if not self.__isVehicleDestroyed: self.__modelAnimators.extend( camouflages.getAttachmentsAnimators(self.__attachments, self.__spaceId, resourceRefs, self.compoundModel)) from vehicle_systems import model_assembler model_assembler.assembleCustomLogicComponents(self, self.__attachments, self.__modelAnimators) for modelAnimator in self.__modelAnimators: modelAnimator.animator.start() def __onSettingsChanged(self, diff): if 'showMarksOnGun' in diff: self.__showMarksOnGun = not diff['showMarksOnGun'] self.refresh() def _getActiveOutfit(self, vDesc): if g_currentPreviewVehicle.isPresent( ) and not g_currentPreviewVehicle.isHeroTank: vehicleCD = g_currentPreviewVehicle.item.descriptor.makeCompactDescr( ) return self.customizationService.getEmptyOutfitWithNationalEmblems( vehicleCD=vehicleCD) elif not g_currentVehicle.isPresent(): if vDesc is not None: vehicleCD = vDesc.makeCompactDescr() outfit = self.customizationService.getEmptyOutfitWithNationalEmblems( vehicleCD=vehicleCD) else: _logger.error( 'Failed to get base vehicle outfit. VehicleDescriptor is None.' ) outfit = self.itemsFactory.createOutfit() return outfit else: vehicle = g_currentVehicle.item season = g_tankActiveCamouflage.get(vehicle.intCD, SeasonType.UNDEFINED) if season == SeasonType.UNDEFINED: season = vehicle.getAnyOutfitSeason() g_tankActiveCamouflage[vehicle.intCD] = season outfit = vehicle.getOutfit(season) if not outfit: vehicleCD = vehicle.descriptor.makeCompactDescr() outfit = self.customizationService.getEmptyOutfitWithNationalEmblems( vehicleCD=vehicleCD) return outfit def __assembleModel(self): from vehicle_systems import model_assembler resources = self.__resources self.__vEntity.model = resources[self.__vDesc.name] if not self.__isVehicleDestroyed: self.__fashions = VehiclePartsTuple(BigWorld.WGVehicleFashion(), BigWorld.WGBaseFashion(), BigWorld.WGBaseFashion(), BigWorld.WGBaseFashion()) model_assembler.setupTracksFashion(self.__vDesc, self.__fashions.chassis) self.__vEntity.model.setupFashions(self.__fashions) model_assembler.assembleCollisionObstaclesCollector( self, None, self.__vDesc, BigWorld.player().spaceID) model_assembler.assembleTessellationCollisionSensor(self, None) wheelsScroll = None wheelsSteering = None if self.__vDesc.chassis.generalWheelsAnimatorConfig is not None: scrollableWheelsCount = self.__vDesc.chassis.generalWheelsAnimatorConfig.getWheelsCount( ) wheelsScroll = [(lambda: 0.0) for _ in xrange(scrollableWheelsCount)] steerableWheelsCount = self.__vDesc.chassis.generalWheelsAnimatorConfig.getSteerableWheelsCount( ) wheelsSteering = [(lambda: 0.0) for _ in xrange(steerableWheelsCount)] chassisFashion = self.__fashions.chassis splineTracksImpl = model_assembler.setupSplineTracks( chassisFashion, self.__vDesc, self.__vEntity.model, self.__resources, self.__outfit.modelsSet) self.wheelsAnimator = model_assembler.createWheelsAnimator( self, ColliderTypes.VEHICLE_COLLIDER, self.__vDesc, lambda: 0, wheelsScroll, wheelsSteering, splineTracksImpl) self.trackNodesAnimator = model_assembler.createTrackNodesAnimator( self, self.__vDesc) model_assembler.assembleTracks(self.__resources, self.__vDesc, self, splineTracksImpl, True) dirtEnabled = BigWorld.WG_dirtEnabled( ) and 'HD' in self.__vDesc.type.tags if dirtEnabled: dirtHandlers = [ BigWorld.PyDirtHandler( True, self.__vEntity.model.node( TankPartNames.CHASSIS).position.y), BigWorld.PyDirtHandler( False, self.__vEntity.model.node( TankPartNames.HULL).position.y), BigWorld.PyDirtHandler( False, self.__vEntity.model.node( TankPartNames.TURRET).position.y), BigWorld.PyDirtHandler( False, self.__vEntity.model.node( TankPartNames.GUN).position.y) ] modelHeight, _ = self.computeVehicleHeight() self.dirtComponent = self.createComponent( Vehicular.DirtComponent, dirtHandlers, modelHeight) for fashionIdx, _ in enumerate(TankPartNames.ALL): self.__fashions[fashionIdx].addMaterialHandler( dirtHandlers[fashionIdx]) self.dirtComponent.setBase() outfitData = camouflages.getOutfitData( self, self.__outfit, self.__vDesc, self.__vState != 'undamaged') self.c11nComponent = self.createComponent( Vehicular.C11nEditComponent, self.__fashions, self.compoundModel, outfitData) self.__updateDecals(self.__outfit) self.__updateSequences(self.__outfit) else: self.__fashions = VehiclePartsTuple(BigWorld.WGVehicleFashion(), BigWorld.WGBaseFashion(), BigWorld.WGBaseFashion(), BigWorld.WGBaseFashion()) self.__vEntity.model.setupFashions(self.__fashions) self.wheelsAnimator = None self.trackNodesAnimator = None self.dirtComponent = None self.flagComponent = None self.__staticTurretYaw = self.__vDesc.gun.staticTurretYaw self.__staticGunPitch = self.__vDesc.gun.staticPitch if not ('AT-SPG' in self.__vDesc.type.tags or 'SPG' in self.__vDesc.type.tags): if self.__staticTurretYaw is None: self.__staticTurretYaw = self._getTurretYaw() turretYawLimits = self.__vDesc.gun.turretYawLimits if turretYawLimits is not None: self.__staticTurretYaw = math_utils.clamp( turretYawLimits[0], turretYawLimits[1], self.__staticTurretYaw) if self.__staticGunPitch is None: self.__staticGunPitch = self._getGunPitch() gunPitchLimits = self.__vDesc.gun.pitchLimits['absolute'] self.__staticGunPitch = math_utils.clamp( gunPitchLimits[0], gunPitchLimits[1], self.__staticGunPitch) else: if self.__staticTurretYaw is None: self.__staticTurretYaw = 0.0 if self.__staticGunPitch is None: self.__staticGunPitch = 0.0 turretYawMatrix = math_utils.createRotationMatrix( (self.__staticTurretYaw, 0.0, 0.0)) self.__vEntity.model.node(TankPartNames.TURRET, turretYawMatrix) gunPitchMatrix = math_utils.createRotationMatrix( (0.0, self.__staticGunPitch, 0.0)) self.__setGunMatrix(gunPitchMatrix) return def __onItemsCacheSyncCompleted(self, updateReason, _): if updateReason == CACHE_SYNC_REASON.DOSSIER_RESYNC and self.__vehicleStickers is not None and self.__getThisVehicleDossierInsigniaRank( ) != self.__vehicleStickers.getCurrentInsigniaRank(): self.refresh() return def __getThisVehicleDossierInsigniaRank(self): if self.__vDesc: vehicleDossier = self.itemsCache.items.getVehicleDossier( self.__vDesc.type.compactDescr) return vehicleDossier.getRandomStats().getAchievement( MARK_ON_GUN_RECORD).getValue() def __setupEmblems(self, outfit): if self.__vehicleStickers is not None: self.__vehicleStickers.detach() insigniaRank = 0 if self.__showMarksOnGun: insigniaRank = self.__getThisVehicleDossierInsigniaRank() self.__vehicleStickers = VehicleStickers.VehicleStickers( self.__vDesc, insigniaRank, outfit) self.__vehicleStickers.alpha = self.__currentEmblemsAlpha self.__vehicleStickers.attach(self.__vEntity.model, self.__isVehicleDestroyed, False) BigWorld.player().stats.get('clanDBID', self.__onClanDBIDRetrieved) return def __onClanDBIDRetrieved(self, _, clanID): self.__vehicleStickers.setClanID(clanID) def __setupModel(self, buildIdx): self.__assembleModel() matrix = math_utils.createSRTMatrix( Math.Vector3(1.0, 1.0, 1.0), Math.Vector3(self.__vEntity.yaw, self.__vEntity.pitch, self.__vEntity.roll), self.__vEntity.position) self.__vEntity.model.matrix = matrix self.__doFinalSetup(buildIdx) self.__vEntity.typeDescriptor = self.__vDesc gunColBox = self.collisions.getBoundingBox( TankPartNames.getIdx(TankPartNames.GUN) + 3) center = 0.5 * (gunColBox[1] - gunColBox[0]) gunoffset = Math.Matrix() gunoffset.setTranslate((0.0, 0.0, center.z + gunColBox[0].z)) gunNode = self.__getGunNode() gunLink = math_utils.MatrixProviders.product(gunoffset, gunNode) collisionData = ((TankPartNames.getIdx(TankPartNames.CHASSIS), self.__vEntity.model.matrix), (TankPartNames.getIdx(TankPartNames.HULL), self.__vEntity.model.node(TankPartNames.HULL)), (TankPartNames.getIdx(TankPartNames.TURRET), self.__vEntity.model.node(TankPartNames.TURRET)), (TankPartNames.getIdx(TankPartNames.GUN), gunNode)) self.collisions.connect(self.__vEntity.id, ColliderTypes.VEHICLE_COLLIDER, collisionData) collisionData = ((TankPartNames.getIdx(TankPartNames.GUN) + 1, self.__vEntity.model.node(TankPartNames.HULL)), (TankPartNames.getIdx(TankPartNames.GUN) + 2, self.__vEntity.model.node(TankPartNames.TURRET)), (TankPartNames.getIdx(TankPartNames.GUN) + 3, gunLink)) self.collisions.connect(self.__vEntity.id, ColliderTypes.HANGAR_VEHICLE_COLLIDER, collisionData) self.__reloadColliderType(self.__vEntity.state) self.__reloadShadowManagerTarget(self.__vEntity.state) def __handleEntityUpdated(self, event): ctx = event.ctx if ctx['entityId'] == self.__vEntity.id: self.__reloadColliderType(ctx['state']) self.__reloadShadowManagerTarget(ctx['state']) def __reloadColliderType(self, state): if not self.collisions: return if state != CameraMovementStates.FROM_OBJECT: colliderData = (self.collisions.getColliderID(), (TankPartNames.getIdx(TankPartNames.GUN) + 1, TankPartNames.getIdx(TankPartNames.GUN) + 2, TankPartNames.getIdx(TankPartNames.GUN) + 3)) BigWorld.appendCameraCollider(colliderData) else: BigWorld.removeCameraCollider(self.collisions.getColliderID()) def __reloadShadowManagerTarget(self, state): if not self.shadowManager or not self.__vEntity.model: return else: if state == CameraMovementStates.ON_OBJECT: self.shadowManager.updatePlayerTarget(self.__vEntity.model) elif state == CameraMovementStates.MOVING_TO_OBJECT: self.shadowManager.updatePlayerTarget(None) return def __doFinalSetup(self, buildIdx): if buildIdx != self.__curBuildInd: return else: self.__loadState.load() if self.__onLoadedCallback is not None: self.__onLoadedCallback() self.__onLoadedCallback = None if self.__onLoadedAfterRefreshCallback is not None: self.__onLoadedAfterRefreshCallback() self.__onLoadedAfterRefreshCallback = None if self.__vDesc is not None and 'observer' in self.__vDesc.type.tags: self.__vEntity.model.visible = False return def __applyAttachmentsVisibility(self): if self.compoundModel is None: return False else: partHandleNotFoundErrorCode = 4294967295L for attachment in self.__attachments: partNode = self.compoundModel.node(attachment.partNodeAlias) if partNode is None: _logger.error('Attachment node "%s" is not found.', attachment.partNodeAlias) continue partId = self.compoundModel.findPartHandleByNode(partNode) if partId == partHandleNotFoundErrorCode: _logger.error('Part handle is not found, see node "%s"', attachment.partNodeAlias) continue if not attachment.initialVisibility: self.compoundModel.setPartVisible(partId, False) return True def getAnchorParams(self, slotId, areaId, regionIdx): if self.__anchorsParams is None: self.__initAnchorsParams() anchorParams = self.__anchorsParams.get(slotId, {}).get(areaId, {}).get(regionIdx) return anchorParams def updateAnchorsParams(self, tankPartsToUpdate=TankPartIndexes.ALL): if self.__anchorsHelpers is None or self.__anchorsParams is None: return else: self.__updateAnchorsParams(tankPartsToUpdate) return def getCentralPointForArea(self, areaIdx): def _getBBCenter(tankPartName): partIdx = TankPartNames.getIdx(tankPartName) boundingBox = Math.Matrix( self.__vEntity.model.getBoundsForPart(partIdx)) bbCenter = boundingBox.applyPoint((0.5, 0.5, 0.5)) return bbCenter if areaIdx == ApplyArea.HULL: trackLeftUpFront = self.__vEntity.model.node( 'HP_TrackUp_LFront').position trackRightUpRear = self.__vEntity.model.node( 'HP_TrackUp_RRear').position position = (trackLeftUpFront + trackRightUpRear) / 2.0 bbCenter = _getBBCenter(TankPartNames.HULL) turretJointPosition = self.__vEntity.model.node( 'HP_turretJoint').position position.y = min(turretJointPosition.y, bbCenter.y) elif areaIdx == ApplyArea.TURRET: position = _getBBCenter(TankPartNames.TURRET) position.y = self.__vEntity.model.node('HP_gunJoint').position.y elif areaIdx == ApplyArea.GUN_2: position = self.__vEntity.model.node('HP_gunJoint').position elif areaIdx == ApplyArea.GUN: gunJointPos = self.__vEntity.model.node('HP_gunJoint').position gunFirePos = self.__vEntity.model.node('HP_gunFire').position position = (gunFirePos + gunJointPos) / 2.0 else: position = _getBBCenter(TankPartNames.CHASSIS) return position def updateCustomization(self, outfit=None, callback=None): if self.__isVehicleDestroyed: return vehicleCD = g_currentVehicle.item.descriptor.makeCompactDescr() outfit = outfit or self.customizationService.getEmptyOutfitWithNationalEmblems( vehicleCD=vehicleCD) if self.recreateRequired(outfit): self.refresh(outfit, callback) return self.__updateCamouflage(outfit) self.__updatePaint(outfit) self.__updateDecals(outfit) self.__updateProjectionDecals(outfit) self.__updateSequences(outfit) def rotateTurretForAnchor(self, anchorId): if self.compoundModel is None or self.__vDesc is None: return False else: defaultYaw = self._getTurretYaw() turretYaw = self.__getTurretYawForAnchor(anchorId, defaultYaw) self.turretRotator.start(turretYaw, rotationTime=EASING_TRANSITION_DURATION) return def rotateGunToDefault(self): if self.compoundModel is None: return False else: localGunMatrix = self.__getGunNode().local currentGunPitch = localGunMatrix.pitch gunPitchAngle = self._getGunPitch() if abs(currentGunPitch - gunPitchAngle) < 0.0001: return False gunPitchMatrix = math_utils.createRotationMatrix( (0.0, gunPitchAngle, 0.0)) self.__setGunMatrix(gunPitchMatrix) return True def __getAnchorHelperById(self, anchorId): if anchorId.slotType not in self.__anchorsHelpers: return None else: slotTypeAnchorHelpers = self.__anchorsHelpers[anchorId.slotType] if anchorId.areaId not in slotTypeAnchorHelpers: return None areaAnchorHelpers = slotTypeAnchorHelpers[anchorId.areaId] return None if anchorId.regionIdx not in areaAnchorHelpers else areaAnchorHelpers[ anchorId.regionIdx] def __updateAnchorHelperWithId(self, anchorId, newAnchorHelper): self.__anchorsHelpers[anchorId.slotType][anchorId.areaId][ anchorId.regionIdx] = newAnchorHelper def __getTurretYawForAnchor(self, anchorId, defaultYaw): turretYaw = defaultYaw if anchorId is not None and hasTurretRotator(self.__vDesc): anchorHelper = self.__getAnchorHelperById(anchorId) if anchorHelper is not None: if anchorHelper.turretYaw is not None: turretYaw = anchorHelper.turretYaw else: if anchorHelper.attachedPartIdx == TankPartIndexes.HULL: needsCorrection = anchorId.slotType in ( GUI_ITEM_TYPE.EMBLEM, GUI_ITEM_TYPE.INSCRIPTION ) or anchorId.slotType == GUI_ITEM_TYPE.PROJECTION_DECAL and anchorHelper.descriptor.showOn == ApplyArea.HULL if needsCorrection: turretYaw = self.__correctTurretYaw( anchorHelper, defaultYaw) anchorHelper = AnchorHelper(anchorHelper.location, anchorHelper.descriptor, turretYaw, anchorHelper.partIdx, anchorHelper.attachedPartIdx) self.__updateAnchorHelperWithId(anchorId, anchorHelper) turretYawLimits = self.__vDesc.gun.turretYawLimits if turretYawLimits is not None: turretYaw = math_utils.clamp(turretYawLimits[0], turretYawLimits[1], turretYaw) return turretYaw def __updatePaint(self, outfit): for fashionIdx, _ in enumerate(TankPartNames.ALL): repaint = camouflages.getRepaint(outfit, fashionIdx, self.__vDesc) self.c11nComponent.setPartPaint(fashionIdx, repaint) def __updateCamouflage(self, outfit): for fashionIdx, descId in enumerate(TankPartNames.ALL): camo = camouflages.getCamo(self, outfit, fashionIdx, self.__vDesc, descId, self.__vState != 'undamaged') self.c11nComponent.setPartCamo(fashionIdx, camo) def __updateDecals(self, outfit): self.__setupEmblems(outfit) def __updateProjectionDecals(self, outfit): decals = camouflages.getGenericProjectionDecals(outfit, self.__vDesc) self.c11nComponent.setDecals(decals) def __updateSequences(self, outfit): resources = camouflages.getModelAnimatorsPrereqs( outfit, self.__spaceId) resources.extend( camouflages.getAttachmentsAnimatorsPrereqs(self.__attachments, self.__spaceId)) if not resources: self.__clearModelAnimators() return BigWorld.loadResourceListBG( tuple(resources), makeCallbackWeak(self.__onAnimatorsLoaded, self.__curBuildInd, outfit)) def __clearModelAnimators(self): self.flagComponent = None for modelAnimator in self.__modelAnimators: modelAnimator.animator.stop() self.__modelAnimators = [] return def __onVehicleChanged(self): self.__anchorsParams = None self.__anchorsHelpers = None return def __initAnchorsParams(self): self.__anchorsParams = { cType: {area: {} for area in Area.ALL} for cType in SLOT_TYPES } if self.__anchorsHelpers is None: self.__initAnchorsHelpers() self.__updateAnchorsParams(TankPartIndexes.ALL) return def __updateAnchorsParams(self, tankPartsToUpdate): tankPartsMatrices = {} for tankPartIdx in TankPartIndexes.ALL: tankPartName = TankPartIndexes.getName(tankPartIdx) tankPartsMatrices[tankPartIdx] = Math.Matrix( self.__vEntity.model.node(tankPartName)) for slotType in SLOT_TYPES: for areaId in Area.ALL: anchorHelpers = self.__anchorsHelpers[slotType][areaId] for regionIdx, anchorHelper in anchorHelpers.iteritems(): attachedPartIdx = anchorHelper.attachedPartIdx if attachedPartIdx not in tankPartsToUpdate: continue anchorLocationWS = self.__getAnchorLocationWS( anchorHelper.location, anchorHelper.partIdx) self.__anchorsParams[slotType][areaId][ regionIdx] = AnchorParams( anchorLocationWS, anchorHelper.descriptor, AnchorId(slotType, areaId, regionIdx)) def __initAnchorsHelpers(self): anchorsHelpers = { cType: {area: {} for area in Area.ALL} for cType in SLOT_TYPES } for slotType in SLOT_TYPES: for areaId in Area.ALL: for regionIdx, anchor in g_currentVehicle.item.getAnchors( slotType, areaId): if isinstance(anchor, EmblemSlot): getAnchorHelper = self.__getEmblemAnchorHelper elif isinstance(anchor, BaseCustomizationSlot): getAnchorHelper = self.__getAnchorHelper else: continue anchorsHelpers[slotType][areaId][ regionIdx] = getAnchorHelper(anchor) self.__anchorsHelpers = anchorsHelpers def __getEmblemAnchorHelper(self, anchor): startPos = anchor.rayStart endPos = anchor.rayEnd normal = startPos - endPos normal.normalise() up = normal * (anchor.descriptor.rayUp * normal) up.normalise() position = startPos + (endPos - startPos) * 0.5 anchorLocation = AnchorLocation(position, normal, up) partIdx = anchor.areaId attachedPartIdx = self.__getAttachedPartIdx(position, normal, partIdx) return AnchorHelper(anchorLocation, anchor.descriptor, None, partIdx, attachedPartIdx) def __getAnchorHelper(self, anchor): slotType = ANCHOR_TYPE_TO_SLOT_TYPE_MAP[anchor.descriptor.type] if slotType in (GUI_ITEM_TYPE.MODIFICATION, GUI_ITEM_TYPE.STYLE): hullAABB = self.collisions.getBoundingBox(TankPartIndexes.HULL) position = Math.Vector3((hullAABB[1].x + hullAABB[0].x) / 2.0, hullAABB[1].y / 2.0, (hullAABB[1].z + hullAABB[0].z) / 2.0) partIdx = TankPartIndexes.HULL else: position = anchor.anchorPosition partIdx = anchor.areaId normal = anchor.anchorDirection normal.normalise() if slotType == GUI_ITEM_TYPE.PROJECTION_DECAL: ypr = anchor.descriptor.rotation rotationMatrix = Math.Matrix() rotationMatrix.setRotateYPR((ypr.y, ypr.x, ypr.z)) up = rotationMatrix.applyVector((0, 0, -1)) else: up = normal * (Math.Vector3(0, 1, 0) * normal) anchorLocation = AnchorLocation(position, normal, up) attachedPartIdx = self.__getAttachedPartIdx(position, normal, partIdx) return AnchorHelper(anchorLocation, anchor.descriptor, None, partIdx, attachedPartIdx) def __getAttachedPartIdx(self, position, normal, tankPartIdx): partMatrix = Math.Matrix( self.__vEntity.model.node(TankPartIndexes.getName(tankPartIdx))) startPos = position + normal * 0.1 endPos = position - normal * 0.6 startPos = partMatrix.applyPoint(startPos) endPos = partMatrix.applyPoint(endPos) collisions = self.collisions.collideAllWorld(startPos, endPos) if collisions is not None: for collision in collisions: partIdx = collision[3] if partIdx in TankPartIndexes.ALL: return partIdx return tankPartIdx def __correctTurretYaw(self, anchorHelper, defaultYaw): if not _SHOULD_CHECK_DECAL_UNDER_GUN: return defaultYaw else: partMatrix = Math.Matrix( self.__vEntity.model.node( TankPartIndexes.getName(anchorHelper.partIdx))) turretMat = Math.Matrix( self.compoundModel.node(TankPartNames.TURRET)) transformMatrix = math_utils.createRTMatrix( (turretMat.yaw, partMatrix.pitch, partMatrix.roll), partMatrix.translation) anchorLocationWS = self.__applyToAnchorLocation( anchorHelper.location, transformMatrix) position = anchorLocationWS.position direction = anchorLocationWS.normal up = anchorLocationWS.up fromTurretToHit = position - turretMat.translation if fromTurretToHit.dot(turretMat.applyVector((0, 0, 1))) < 0: return defaultYaw checkDirWorld = direction * 10.0 cornersWorldSpace = self.__getDecalCorners(position, direction, up, anchorHelper.descriptor) if cornersWorldSpace is None: return defaultYaw slotType = ANCHOR_TYPE_TO_SLOT_TYPE_MAP[ anchorHelper.descriptor.type] if slotType == GUI_ITEM_TYPE.PROJECTION_DECAL: turretLeftDir = turretMat.applyVector((1, 0, 0)) turretLeftDir.normalise() gunJoin = self.__vEntity.model.node('HP_gunJoint') fromGunJointToAnchor = gunJoin.position - position decalDiags = (cornersWorldSpace[0] - cornersWorldSpace[2], cornersWorldSpace[1] - cornersWorldSpace[3]) fromGunToHit = abs(fromGunJointToAnchor.dot(turretLeftDir)) halfDecalWidth = max((abs(decalDiag.dot(turretLeftDir)) for decalDiag in decalDiags)) * 0.5 if fromGunToHit > halfDecalWidth * _PROJECTION_DECAL_OVERLAPPING_FACTOR: return defaultYaw result = self.collisions.collideShape(TankPartIndexes.GUN, cornersWorldSpace, checkDirWorld) if result < 0.0: return defaultYaw turretYaw = _HANGAR_TURRET_SHIFT gunDir = turretMat.applyVector(Math.Vector3(0, 0, 1)) if Math.Vector3(0, 1, 0).dot(gunDir * fromTurretToHit) > 0.0: turretYaw = -turretYaw return turretYaw def __getDecalCorners(self, position, direction, up, slotDescriptor): slotType = ANCHOR_TYPE_TO_SLOT_TYPE_MAP[slotDescriptor.type] if slotType == GUI_ITEM_TYPE.PROJECTION_DECAL: width = slotDescriptor.scale[0] aspect = getProgectionDecalAspect(slotDescriptor) height = slotDescriptor.scale[2] * aspect else: width = slotDescriptor.size aspect = SLOT_ASPECT_RATIO.get(slotType) if aspect is not None: height = width * aspect else: return transformMatrix = Math.Matrix() transformMatrix.lookAt(position, direction, up) transformMatrix.invert() result = (Math.Vector3(width * 0.5, height * 0.5, 0), Math.Vector3(width * 0.5, -height * 0.5, 0), Math.Vector3(-width * 0.5, -height * 0.5, 0), Math.Vector3(-width * 0.5, height * 0.5, 0)) return tuple((transformMatrix.applyPoint(vec) for vec in result)) def __applyToAnchorLocation(self, anchorLocation, transform): position = transform.applyPoint(anchorLocation.position) normal = transform.applyVector(anchorLocation.normal) up = transform.applyVector(anchorLocation.up) if abs(normal.pitch - math.pi / 2) < 0.1: normal = Math.Vector3(0, -1, 0) + up * 0.01 normal.normalise() return AnchorLocation(position, normal, up) def __getAnchorLocationWS(self, anchorLocation, partIdx): partMatrix = Math.Matrix( self.__vEntity.model.node(TankPartIndexes.getName(partIdx))) return self.__applyToAnchorLocation(anchorLocation, partMatrix) def __getGunNode(self): gunNode = self.compoundModel.node(TankNodeNames.GUN_INCLINATION) if gunNode is None: gunNode = self.compoundModel.node(TankPartNames.GUN) return gunNode def __setGunMatrix(self, gunMatrix): gunNode = self.__getGunNode() gunNode.local = gunMatrix
class PlaneLootAirdrop(ScriptGameObject, CallbackDelayer, ISelfAssembler): __dynamicObjectsCache = dependency.descriptor(IBattleDynamicObjectsCache) __sessionProvider = dependency.descriptor(IBattleSessionProvider) FLY_TIME_BEFORE_DROP = DropPlane.FLY_TIME_BEFORE_DROP FLY_TIME_AFTER_DROP = DropPlane.FLY_TIME_AFTER_DROP DESCEND_TIME = 7 DROP_ALTITUDE = 50 POST_DELIVERY_CARGO_LIFETIME = 12.0 cargo = ComponentDescriptor() plane = ComponentDescriptor() def __init__(self, dropID, deliveryPosition, deliveryTime): ScriptGameObject.__init__(self, BigWorld.player().spaceID) CallbackDelayer.__init__(self) self.owner = Svarog.GameObject(BigWorld.player().spaceID) self.owner.activate() self.owner.addComponent(self) Svarog.addGameObject(BigWorld.player().spaceID, self.owner) self.id = dropID self.deliveryPosition = deliveryPosition self.deliveryTime = deliveryTime + BigWorld.time( ) - BigWorld.serverTime() self.onFlightEnd = Event() def start(self, *args, **kwargs): planeStartTime = self.deliveryTime - self.FLY_TIME_BEFORE_DROP self.delayCallback(planeStartTime - BigWorld.time(), self.__launchPlane) dropStartTime = self.deliveryTime - self.DESCEND_TIME self.delayCallback(dropStartTime - BigWorld.time(), self.__dropCrate) self.inactiveCargo = None self.activate() return def destroy(self): if self.inactiveCargo is not None: self.inactiveCargo.stopLoading = True self.inactiveCargo.destroy() self.inactiveCargo = None if self.cargo: self.cargo.stopLoading = True ScriptGameObject.destroy(self) CallbackDelayer.destroy(self) return def __launchPlane(self): self.plane = DropPlane(self.deliveryPosition, self.DROP_ALTITUDE, self.deliveryTime - self.DESCEND_TIME) self.delayCallback( self.deliveryTime + self.FLY_TIME_AFTER_DROP - BigWorld.time(), self.__processFlightEnd) def __dropCrate(self): airDropConfig = self.__dynamicObjectsCache.getConfig( self.__sessionProvider.arenaVisitor.getArenaGuiType()).getAirDrop( ) spaceId = BigWorld.player().spaceID compoundName = 'crateModel' modelAssembler = BigWorld.CompoundAssembler(compoundName, spaceId) modelAssembler.addRootPart(airDropConfig.model, 'root') animationPath = airDropConfig.dropAnimation animationBuilder = AnimationSequence.Loader(animationPath, spaceId) dropPoint = self.deliveryPosition + Math.Vector3( 0, self.DROP_ALTITUDE, 0) crateYaw = 0 if self.plane is not None: crateYaw = self.plane.flightYaw self.inactiveCargo = parachuteCargo = ParachuteCargo( crateYaw, dropPoint, self.deliveryPosition, self.DESCEND_TIME) loadComponentSystem( parachuteCargo, self.__onCargoLoad, { 'model': Loader(modelAssembler), 'landingAnimation': Loader(animationBuilder) }) self.delayCallback( self.deliveryTime - BigWorld.time() + self.POST_DELIVERY_CARGO_LIFETIME, self.__killCargo) return def __onCargoLoad(self, cargo): self.cargo = cargo self.inactiveCargo = None cargo.activate() return def __killCargo(self): self.cargo = None return def __processFlightEnd(self): self.onFlightEnd(self) self.plane = None Svarog.removeGameObject(self.owner.worldID, self.owner) return
class ClientSelectableObject(BigWorld.Entity, ScriptGameObject, ISelectableObject): collisions = ComponentDescriptor() @property def enabled(self): return self.__enabled def __init__(self): BigWorld.Entity.__init__(self) ScriptGameObject.__init__(self, self.spaceID) ISelectableObject.__init__(self) self.__enabled = True self.__edged = False self.__clickSound = None self.model = None return def prerequisites(self): if not self.modelName: return [] collisionModels = self._getCollisionModelsPrereqs() collisionAssembler = BigWorld.CollisionAssembler( collisionModels, self.spaceID) return [self.modelName, collisionAssembler] def onEnterWorld(self, prereqs): if not self.modelName: return if self.modelName not in prereqs.failedIDs: model = prereqs[self.modelName] self.model = model self.filter = BigWorld.DumbFilter() self.model.addMotor(BigWorld.Servo(self.matrix)) self.collisions = prereqs['collisionAssembler'] collisionData = ((0, self.model.matrix), ) self.collisions.connect(self.id, ColliderTypes.DYNAMIC_COLLIDER, collisionData) ScriptGameObject.activate(self) def onLeaveWorld(self): ScriptGameObject.deactivate(self) ScriptGameObject.destroy(self) if self.__clickSound is not None: if self.__clickSound.isPlaying: self.__clickSound.stop() self.__clickSound.releaseMatrix() self.__clickSound = None self.setHighlight(False) return def setEnable(self, enabled): self.__enabled = enabled if not self.__enabled: self.setHighlight(False) def setHighlight(self, show): if show: if not self.__edged and self.__enabled: self._addEdgeDetect() self.__edged = True elif self.__edged: self._delEdgeDetect() self.__edged = False def onMouseDown(self): pass def onMouseUp(self): pass def onMouseClick(self): if self.__clickSound is None: if self.clickSoundName and self.__enabled: if self.isClick3DSound: self.__clickSound = SoundGroups.g_instance.getSound3D( self.model.root, self.clickSoundName) else: self.__clickSound = SoundGroups.g_instance.getSound2D( self.clickSoundName) self.__clickSound.play() elif self.__clickSound.isPlaying: self.__clickSound.stop() else: self.__clickSound.play() return def _getModelHeight(self): return self.model.height def _getCollisionModelsPrereqs(self): collisionModels = ((0, self.modelName), ) return collisionModels def _addEdgeDetect(self): BigWorld.wgAddEdgeDetectEntity(self, 0, self.edgeMode, False) def _delEdgeDetect(self): BigWorld.wgDelEdgeDetectEntity(self)
class AvatarInputHandler(CallbackDelayer, ScriptGameObject): bootcampCtrl = dependency.descriptor(IBootcampController) ctrl = property(lambda self: self.__curCtrl) ctrls = property(lambda self: self.__ctrls) isSPG = property(lambda self: self.__isSPG) isATSPG = property(lambda self: self.__isATSPG) isDualGun = property(lambda self: self.__isDualGun) isMagneticAimEnabled = property(lambda self: self.__isMagnetAimEnabled) isFlashBangAllowed = property(lambda self: self.__ctrls['video'] != self.__curCtrl) isDetached = property(lambda self: self.__isDetached) isGuiVisible = property(lambda self: self.__isGUIVisible) isStarted = property(lambda self: self.__isStarted) isObserverFPV = property(lambda self: BigWorld.player().isObserver() and BigWorld.player().isObserverFPV) remoteCameraSender = property(lambda self: self.__remoteCameraSender) __ctrlModeName = aih_global_binding.bindRW(_BINDING_ID.CTRL_MODE_NAME) __aimOffset = aih_global_binding.bindRW(_BINDING_ID.AIM_OFFSET) _DYNAMIC_CAMERAS_ENABLED_KEY = 'global/dynamicCameraEnabled' settingsCore = dependency.descriptor(ISettingsCore) appLoader = dependency.descriptor(IAppLoader) @staticmethod def enableDynamicCamera(enable, useHorizontalStabilizer=True): for dynamicCameraClass in _DYNAMIC_CAMERAS: dynamicCameraClass.enableDynamicCamera(enable) SniperAimingSystem.setStabilizerSettings(useHorizontalStabilizer, True) @staticmethod def isCameraDynamic(): for dynamicCameraClass in _DYNAMIC_CAMERAS: if not dynamicCameraClass.isCameraDynamic(): return False return True @staticmethod def isSniperStabilized(): return SniperAimingSystem.getStabilizerSettings() @property def ctrlModeName(self): return self.__ctrlModeName siegeModeControl = ComponentDescriptor() dualGunControl = ComponentDescriptor() siegeModeSoundNotifications = ComponentDescriptor() steadyVehicleMatrixCalculator = ComponentDescriptor() def __init__(self): CallbackDelayer.__init__(self) ScriptGameObject.__init__(self, BigWorld.player().spaceID) self.__alwaysShowAimKey = None self.__showMarkersKey = None sec = self._readCfg() self.onCameraChanged = Event() self.onPostmortemVehicleChanged = Event() self.onPostmortemKillerVisionEnter = Event() self.onPostmortemKillerVisionExit = Event() self.__isArenaStarted = False self.__isStarted = False self.__targeting = _Targeting() self.__vertScreenshotCamera = _VertScreenshotCamera() self.__ctrls = dict() self.__killerVehicleID = None self.__isAutorotation = True self.__prevModeAutorotation = None self.__isSPG = False self.__isATSPG = False self.__isDualGun = False self.__isMagnetAimEnabled = False self.__setupCtrls(sec) self.__curCtrl = self.__ctrls[_CTRLS_FIRST] self.__ctrlModeName = _CTRLS_FIRST self.__isDetached = False self.__waitObserverCallback = None self.__observerVehicle = None self.__observerIsSwitching = False self.__commands = [] self.__detachedCommands = [] self.__remoteCameraSender = None self.__isGUIVisible = False return def __constructComponents(self): player = BigWorld.player() typeDescr = player.vehicleTypeDescriptor if typeDescr.hasSiegeMode: if not self.siegeModeControl: self.siegeModeControl = SiegeModeControl() self.__commands.append(self.siegeModeControl) self.siegeModeControl.onSiegeStateChanged += lambda *args: self.steadyVehicleMatrixCalculator.relinkSources() if not self.siegeModeSoundNotifications: notifications = None if typeDescr.hasHydraulicChassis: notifications = SiegeModeSoundNotifications() elif typeDescr.hasTurboshaftEngine: notifications = TurboshaftModeSoundNotifications() if notifications: self.siegeModeSoundNotifications = notifications self.siegeModeControl.onSiegeStateChanged += self.siegeModeSoundNotifications.onSiegeStateChanged self.siegeModeControl.onRequestFail += self.__onRequestFail self.siegeModeControl.onSiegeStateChanged += SiegeModeCameraShaker.shake if typeDescr.isDualgunVehicle and not self.dualGunControl: self.dualGunControl = DualGunController(typeDescr) elif not typeDescr.isDualgunVehicle: self.dualGunControl = None if self.bootcampCtrl.isInBootcamp() and constants.HAS_DEV_RESOURCES: self.__commands.append(BootcampModeControl()) if ARENA_BONUS_TYPE_CAPS.checkAny(player.arena.bonusType, ARENA_BONUS_TYPE_CAPS.RADAR): self.__commands.append(RadarControl()) if ARENA_BONUS_TYPE_CAPS.checkAny(player.arena.bonusType, ARENA_BONUS_TYPE_CAPS.BATTLEROYALE): self.__commands.append(VehicleUpdateControl()) self.__commands.append(VehicleUpgradePanelControl()) self.__detachedCommands.append(VehicleUpgradePanelControl()) return def prerequisites(self): out = [] for ctrl in self.__ctrls.itervalues(): out += ctrl.prerequisites() return out def handleKeyEvent(self, event): import game isDown, key, mods, isRepeat = game.convertKeyEvent(event) if isRepeat: return False elif self.__isStarted and self.__isDetached: if self.__curCtrl.alwaysReceiveKeyEvents(isDown=isDown) and not self.isObserverFPV or CommandMapping.g_instance.isFired(CommandMapping.CMD_CM_LOCK_TARGET, key): self.__curCtrl.handleKeyEvent(isDown, key, mods, event) for command in self.__detachedCommands: if command.handleKeyEvent(isDown, key, mods, event): return True return BigWorld.player().handleKey(isDown, key, mods) elif not self.__isStarted or self.__isDetached: return False for command in self.__commands: if command.handleKeyEvent(isDown, key, mods, event): return True if isDown and BigWorld.isKeyDown(Keys.KEY_CAPSLOCK): if self.__alwaysShowAimKey is not None and key == self.__alwaysShowAimKey: gui_event_dispatcher.toggleCrosshairVisibility() return True if self.__showMarkersKey is not None and key == self.__showMarkersKey and not self.__isGUIVisible: gui_event_dispatcher.toggleMarkers2DVisibility() return True if key == Keys.KEY_F5 and constants.HAS_DEV_RESOURCES: self.__vertScreenshotCamera.enable(not self.__vertScreenshotCamera.isEnabled) return True if key == Keys.KEY_SPACE and isDown and BigWorld.player().isObserver(): BigWorld.player().cell.switchObserverFPV(not BigWorld.player().isObserverFPV) return True else: return True if not self.isObserverFPV and self.__curCtrl.handleKeyEvent(isDown, key, mods, event) else BigWorld.player().handleKey(isDown, key, mods) def handleMouseEvent(self, dx, dy, dz): return False if not self.__isStarted or self.__isDetached else self.__curCtrl.handleMouseEvent(dx, dy, dz) def setForcedGuiControlMode(self, flags): result = False detached = flags & GUI_CTRL_MODE_FLAG.CURSOR_ATTACHED > 0 if detached ^ self.__isDetached: self.__isDetached = detached self.__targeting.detach(self.__isDetached) if detached: self.appLoader.attachCursor(settings.APP_NAME_SPACE.SF_BATTLE, flags=flags) result = True if flags & GUI_CTRL_MODE_FLAG.AIMING_ENABLED > 0: self.setAimingMode(False, AIMING_MODE.USER_DISABLED) else: self.appLoader.detachCursor(settings.APP_NAME_SPACE.SF_BATTLE) result = True self.__curCtrl.setForcedGuiControlMode(detached) elif detached: self.appLoader.syncCursor(settings.APP_NAME_SPACE.SF_BATTLE, flags=flags) return result def updateShootingStatus(self, canShoot): return None if self.__isDetached else self.__curCtrl.updateShootingStatus(canShoot) def getDesiredShotPoint(self, ignoreAimingMode=False): return None if self.__isDetached else self.__curCtrl.getDesiredShotPoint(ignoreAimingMode) def getMarkerPoint(self): point = None if self.__ctrlModeName in (_CTRL_MODE.ARCADE, _CTRL_MODE.STRATEGIC, _CTRL_MODE.ARTY): AimingSystems.shootInSkyPoint.has_been_called = False point = self.getDesiredShotPoint(ignoreAimingMode=True) if AimingSystems.shootInSkyPoint.has_been_called: point = None return point def showGunMarker(self, isShown): self.__curCtrl.setGunMarkerFlag(isShown, _GUN_MARKER_FLAG.CLIENT_MODE_ENABLED) def showGunMarker2(self, isShown): if not BattleReplay.isPlaying(): self.__curCtrl.setGunMarkerFlag(isShown, _GUN_MARKER_FLAG.SERVER_MODE_ENABLED) if gun_marker_ctrl.useDefaultGunMarkers(): self.__curCtrl.setGunMarkerFlag(not isShown, _GUN_MARKER_FLAG.CLIENT_MODE_ENABLED) replayCtrl = BattleReplay.g_replayCtrl replayCtrl.setUseServerAim(isShown) def updateGunMarker(self, pos, direction, size, relaxTime, collData): self.__curCtrl.updateGunMarker(_GUN_MARKER_TYPE.CLIENT, pos, direction, size, relaxTime, collData) def updateGunMarker2(self, pos, direction, size, relaxTime, collData): self.__curCtrl.updateGunMarker(_GUN_MARKER_TYPE.SERVER, pos, direction, size, relaxTime, collData) def setAimingMode(self, enable, mode): self.__curCtrl.setAimingMode(enable, mode) def getAimingMode(self, mode): return self.__curCtrl.getAimingMode(mode) def setAutorotation(self, bValue): if not self.__curCtrl.enableSwitchAutorotationMode(): return elif not BigWorld.player().isOnArena: return else: if self.__isAutorotation != bValue: self.__isAutorotation = bValue BigWorld.player().enableOwnVehicleAutorotation(self.__isAutorotation) self.__prevModeAutorotation = None return def getAutorotation(self): return self.__isAutorotation def switchAutorotation(self): self.setAutorotation(not self.__isAutorotation) def activatePostmortem(self, isRespawn): if self.siegeModeSoundNotifications is not None: self.siegeModeSoundNotifications = None BigWorld.player().autoAim(None) for ctlMode in self.__ctrls.itervalues(): ctlMode.resetAimingMode() try: params = self.__curCtrl.postmortemCamParams except Exception: params = None onPostmortemActivation = getattr(self.__curCtrl, 'onPostmortemActivation', None) if onPostmortemActivation is not None: onPostmortemActivation(_CTRL_MODE.POSTMORTEM, postmortemParams=params, bPostmortemDelay=True, respawn=isRespawn) else: self.onControlModeChanged(_CTRL_MODE.POSTMORTEM, postmortemParams=params, bPostmortemDelay=True, respawn=isRespawn) return def deactivatePostmortem(self): self.onControlModeChanged('arcade') arcadeMode = self.__ctrls['arcade'] arcadeMode.camera.setToVehicleDirection() self.__identifyVehicleType() self.__constructComponents() def setKillerVehicleID(self, killerVehicleID): self.__killerVehicleID = killerVehicleID def getKillerVehicleID(self): return self.__killerVehicleID def start(self): g_guiResetters.add(self.__onRecreateDevice) self.steadyVehicleMatrixCalculator = SteadyVehicleMatrixCalculator() self.__identifyVehicleType() self.__constructComponents() for control in self.__ctrls.itervalues(): control.create() avatar = BigWorld.player() if not self.__curCtrl.isManualBind(): avatar.positionControl.bindToVehicle(True) self.__curCtrl.enable() tmp = self.__curCtrl.getPreferredAutorotationMode() if tmp is not None: self.__isAutorotation = tmp self.__prevModeAutorotation = True else: self.__isAutorotation = True self.__prevModeAutorotation = None avatar.enableOwnVehicleAutorotation(self.__isAutorotation) self.__targeting.enable(True) self.__isStarted = True self.__isGUIVisible = True self.__killerVehicleID = None arena = avatar.arena arena.onPeriodChange += self.__onArenaStarted self.settingsCore.onSettingsChanged += self.__onSettingsChanged avatar.consistentMatrices.onVehicleMatrixBindingChanged += self.__onVehicleChanged self.__onArenaStarted(arena.period) if not avatar.isObserver() and arena.hasObservers: self.__remoteCameraSender = RemoteCameraSender(self) self.onCameraChanged('arcade') return def stop(self): self.__isStarted = False import SoundGroups SoundGroups.g_instance.changePlayMode(0) aih_global_binding.clear() for control in self.__ctrls.itervalues(): control.destroy() replayCtrl = BattleReplay.g_replayCtrl if replayCtrl.isRecording: replayCtrl.setPlayerVehicleID(0) if self.__remoteCameraSender is not None: self.__remoteCameraSender.destroy() self.__remoteCameraSender = None self.onCameraChanged.clear() self.onCameraChanged = None self.onPostmortemVehicleChanged.clear() self.onPostmortemVehicleChanged = None self.onPostmortemKillerVisionEnter.clear() self.onPostmortemKillerVisionEnter = None self.onPostmortemKillerVisionExit.clear() self.onPostmortemKillerVisionExit = None self.__targeting.enable(False) self.__killerVehicleID = None if self.__onRecreateDevice in g_guiResetters: g_guiResetters.remove(self.__onRecreateDevice) BigWorld.player().arena.onPeriodChange -= self.__onArenaStarted self.settingsCore.onSettingsChanged -= self.__onSettingsChanged BigWorld.player().consistentMatrices.onVehicleMatrixBindingChanged -= self.__onVehicleChanged ScriptGameObject.destroy(self) CallbackDelayer.destroy(self) return def __onVehicleChanged(self, isStatic): self.steadyVehicleMatrixCalculator.relinkSources() self.__commands = [] self.__identifyVehicleType() self.__constructComponents() if self.__waitObserverCallback is not None and self.__observerVehicle is not None: player = BigWorld.player() ownVehicle = BigWorld.entity(player.playerVehicleID) vehicle = player.getVehicleAttached() if vehicle != ownVehicle: self.__waitObserverCallback() self.__observerIsSwitching = False self.__observerVehicle = None return def setObservedVehicle(self, vehicleID): for control in self.__ctrls.itervalues(): control.setObservedVehicle(vehicleID) def onControlModeChanged(self, eMode, **args): if self.steadyVehicleMatrixCalculator is not None: self.steadyVehicleMatrixCalculator.relinkSources() if not self.__isArenaStarted and eMode != _CTRL_MODE.POSTMORTEM: return else: player = BigWorld.player() isObserverMode = 'observer' in player.vehicleTypeDescriptor.type.tags if player is not None else True if self.__waitObserverCallback is not None: self.__waitObserverCallback = None if not isObserverMode and self.__isDualGun: gui_event_dispatcher.controlModeChange(eMode) if isObserverMode and eMode == _CTRL_MODE.POSTMORTEM: if self.__observerVehicle is not None and not self.__observerIsSwitching: self.__waitObserverCallback = partial(self.onControlModeChanged, eMode, **args) self.__observerIsSwitching = True player.positionControl.followCamera(False) player.positionControl.bindToVehicle(True, self.__observerVehicle) return if isObserverMode and self.__ctrlModeName == _CTRL_MODE.POSTMORTEM: player = BigWorld.player() self.__observerVehicle = player.vehicle.id if player.vehicle else None self.__observerIsSwitching = False replayCtrl = BattleReplay.g_replayCtrl if replayCtrl.isRecording: replayCtrl.setControlMode(eMode) self.__curCtrl.disable() prevCtrl = self.__curCtrl self.__curCtrl = self.__ctrls[eMode] self.__ctrlModeName = eMode if player is not None: if not prevCtrl.isManualBind() and self.__curCtrl.isManualBind(): if isObserverMode: player.positionControl.bindToVehicle(False, -1) else: player.positionControl.bindToVehicle(False) elif prevCtrl.isManualBind() and not self.__curCtrl.isManualBind(): if isObserverMode: player.positionControl.followCamera(False) player.positionControl.bindToVehicle(True, self.__observerVehicle) else: player.positionControl.bindToVehicle(True) elif not prevCtrl.isManualBind() and not self.__curCtrl.isManualBind(): if isObserverMode and not self.isObserverFPV: player.positionControl.bindToVehicle(True) newAutoRotationMode = self.__curCtrl.getPreferredAutorotationMode() if newAutoRotationMode is not None: if prevCtrl.getPreferredAutorotationMode() is None: self.__prevModeAutorotation = self.__isAutorotation if self.__isAutorotation != newAutoRotationMode: self.__isAutorotation = newAutoRotationMode BigWorld.player().enableOwnVehicleAutorotation(self.__isAutorotation) elif prevCtrl.getPreferredAutorotationMode() is not None: if self.__prevModeAutorotation is None: self.__prevModeAutorotation = True if self.__isAutorotation != self.__prevModeAutorotation: self.__isAutorotation = self.__prevModeAutorotation BigWorld.player().enableOwnVehicleAutorotation(self.__isAutorotation) self.__prevModeAutorotation = None if not isObserverMode and self.__ctrlModeName in (_CTRL_MODE.ARCADE, _CTRL_MODE.SNIPER): lockEnabled = prevCtrl.getAimingMode(AIMING_MODE.TARGET_LOCK) self.__curCtrl.setAimingMode(lockEnabled, AIMING_MODE.TARGET_LOCK) self.__targeting.onRecreateDevice() self.__curCtrl.setGUIVisible(self.__isGUIVisible) if isObserverMode: args.update(vehicleID=self.__observerVehicle) self.__curCtrl.enable(**args) else: self.__curCtrl.enable(**args) isReplayPlaying = replayCtrl.isPlaying vehicleID = None vehicle = player.getVehicleAttached() if isObserverMode: vehicleID = self.__observerVehicle elif vehicle is not None and isReplayPlaying: vehicleID = vehicle.id self.onCameraChanged(eMode, vehicleID) if not isReplayPlaying and not vehicle.isUpgrading: self.__curCtrl.handleMouseEvent(0.0, 0.0, 0.0) return def onVehicleControlModeChanged(self, eMode): LOG_DEBUG('onVehicleControlModeChanged: ', eMode, self.isObserverFPV) if not self.isObserverFPV: self.onControlModeChanged(_CTRL_MODE.POSTMORTEM) return else: if eMode is None: eMode = _CTRL_MODES[BigWorld.player().observerFPVControlMode] targetPos = self.getDesiredShotPoint() or Math.Vector3(0, 0, 0) LOG_DEBUG('onVehicleControlModeChanged: ', eMode, targetPos) vehicle = BigWorld.player().getVehicleAttached() self.onControlModeChanged(eMode, preferredPos=targetPos, aimingMode=0, saveZoom=False, saveDist=True, equipmentID=None, curVehicleID=vehicle.id if vehicle is not None else BigWorld.player().playerVehicleID) return def getTargeting(self): return self.__targeting def setGUIVisible(self, isVisible): self.__isGUIVisible = isVisible self.__curCtrl.setGUIVisible(isVisible) def selectPlayer(self, vehId): self.__curCtrl.selectPlayer(vehId) def onMinimapClicked(self, worldPos): return self.__curCtrl.onMinimapClicked(worldPos) def onVehicleShaken(self, vehicle, impulsePosition, impulseDir, caliber, shakeReason): if shakeReason == _ShakeReason.OWN_SHOT_DELAYED: shakeFuncBound = functools.partial(self.onVehicleShaken, vehicle, impulsePosition, impulseDir, caliber, _ShakeReason.OWN_SHOT) delayTime = self.__dynamicCameraSettings.settings['ownShotImpulseDelay'] self.delayCallback(delayTime, shakeFuncBound) return else: camera = getattr(self.ctrl, 'camera', None) if camera is None: return impulseValue = self.__dynamicCameraSettings.getGunImpulse(caliber) vehicleSensitivity = 0.0 avatarVehicle = BigWorld.player().getVehicleAttached() if avatarVehicle is None or not avatarVehicle.isAlive(): return avatarVehicleTypeDesc = getattr(avatarVehicle, 'typeDescriptor', None) if avatarVehicleTypeDesc is not None: avatarVehWeightTons = avatarVehicleTypeDesc.physics['weight'] / 1000.0 vehicleSensitivity = self.__dynamicCameraSettings.getSensitivityToImpulse(avatarVehWeightTons) vehicleSensitivity *= avatarVehicleTypeDesc.hull.swinging.sensitivityToImpulse impulseReason = None isDistant = False if shakeReason == _ShakeReason.OWN_SHOT: if vehicle is avatarVehicle: impulseReason = cameras.ImpulseReason.MY_SHOT isDistant = False else: impulseReason = cameras.ImpulseReason.OTHER_SHOT isDistant = True elif vehicle is avatarVehicle: if shakeReason == _ShakeReason.HIT or shakeReason == _ShakeReason.HIT_NO_DAMAGE: impulseValue *= 1.0 if shakeReason == _ShakeReason.HIT else self.__dynamicCameraSettings.settings['zeroDamageHitSensitivity'] impulseReason = cameras.ImpulseReason.ME_HIT isDistant = False else: impulseReason = cameras.ImpulseReason.SPLASH isDistant = True impulseDir, impulseValue = self.__adjustImpulse(impulseDir, impulseValue, camera, impulsePosition, vehicleSensitivity, impulseReason) if isDistant: camera.applyDistantImpulse(impulsePosition, impulseValue, impulseReason) else: camera.applyImpulse(impulsePosition, impulseDir * impulseValue, impulseReason) return def onVehicleCollision(self, vehicle, impactVelocity): if impactVelocity < self.__dynamicCameraSettings.settings['minCollisionSpeed']: return else: camera = getattr(self.ctrl, 'camera', None) if camera is None: return avatarVehicle = BigWorld.player().getVehicleAttached() if avatarVehicle is None or not avatarVehicle.isAlive(): return if vehicle is avatarVehicle: impulse = Math.Vector3(0, impactVelocity * self.__dynamicCameraSettings.settings['collisionSpeedToImpulseRatio'], 0) camera.applyImpulse(vehicle.position, impulse, cameras.ImpulseReason.COLLISION) return def onVehicleDeath(self, vehicle, exploded): if not exploded: return else: camera = getattr(self.ctrl, 'camera', None) if camera is None: return avatarVehicle = BigWorld.player().getVehicleAttached() if avatarVehicle is None or avatarVehicle is vehicle: return caliber = vehicle.typeDescriptor.shot.shell.caliber impulseValue = self.__dynamicCameraSettings.getGunImpulse(caliber) avatarVehicleWeightInTons = avatarVehicle.typeDescriptor.physics['weight'] / 1000.0 vehicleSensitivity = self.__dynamicCameraSettings.getSensitivityToImpulse(avatarVehicleWeightInTons) vehicleSensitivity *= avatarVehicle.typeDescriptor.hull.swinging.sensitivityToImpulse _, impulseValue = self.__adjustImpulse(Math.Vector3(0, 0, 0), impulseValue, camera, vehicle.position, vehicleSensitivity, cameras.ImpulseReason.VEHICLE_EXPLOSION) camera.applyDistantImpulse(vehicle.position, impulseValue, cameras.ImpulseReason.VEHICLE_EXPLOSION) return def onExplosionImpulse(self, position, impulseValue): camera = getattr(self.ctrl, 'camera', None) if camera is None: return else: avatarVehicle = BigWorld.player().getVehicleAttached() if avatarVehicle is None: return avatarVehicleWeightInTons = avatarVehicle.typeDescriptor.physics['weight'] / 1000.0 vehicleSensitivity = self.__dynamicCameraSettings.getSensitivityToImpulse(avatarVehicleWeightInTons) vehicleSensitivity *= avatarVehicle.typeDescriptor.hull.swinging.sensitivityToImpulse _, impulseValue = self.__adjustImpulse(Math.Vector3(0, 0, 0), impulseValue, camera, position, vehicleSensitivity, cameras.ImpulseReason.HE_EXPLOSION) camera.applyDistantImpulse(position, impulseValue, cameras.ImpulseReason.HE_EXPLOSION) return def onProjectileHit(self, position, caliber, isOwnShot): if not isOwnShot: return else: camera = getattr(self.ctrl, 'camera', None) if camera is None: return impulseValue = self.__dynamicCameraSettings.getGunImpulse(caliber) vehicleSensitivity = 1.0 avatarVehicle = BigWorld.player().getVehicleAttached() if avatarVehicle is not None: avatarVehicleWeightInTons = avatarVehicle.typeDescriptor.physics['weight'] / 1000.0 vehicleSensitivity = self.__dynamicCameraSettings.getSensitivityToImpulse(avatarVehicleWeightInTons) vehicleSensitivity *= avatarVehicle.typeDescriptor.hull.swinging.sensitivityToImpulse _, impulseValue = self.__adjustImpulse(Math.Vector3(0, 0, 0), impulseValue, camera, position, vehicleSensitivity, cameras.ImpulseReason.VEHICLE_EXPLOSION) camera.applyDistantImpulse(position, impulseValue, cameras.ImpulseReason.PROJECTILE_HIT) return def onSpecificImpulse(self, position, impulse, specificCtrl=None): if specificCtrl is None: camera = getattr(self.ctrl, 'camera', None) else: camera = self.ctrls[specificCtrl].camera if camera is None: return else: camera.applyImpulse(position, impulse, cameras.ImpulseReason.MY_SHOT) return def __adjustImpulse(self, impulseDir, impulseValue, camera, impulsePosition, vehicleSensitivity, impulseReason): if impulseReason in camera.getReasonsAffectCameraDirectly(): dirToCamera = camera.camera.position - impulsePosition dirToCamera.normalise() impulseDir = dirToCamera else: impulseValue *= vehicleSensitivity return (impulseDir, impulseValue) def __identifyVehicleType(self): avatar = BigWorld.player() magnetAimTags = avatar.magneticAutoAimTags veh = BigWorld.entity(avatar.playerVehicleID) if veh is None: return else: vehTypeDesc = veh.typeDescriptor.type self.__isSPG = 'SPG' in vehTypeDesc.tags self.__isATSPG = 'AT-SPG' in vehTypeDesc.tags self.__isDualGun = veh.typeDescriptor.isDualgunVehicle self.__isMagnetAimEnabled = bool(magnetAimTags & vehTypeDesc.tags) return def reloadDynamicSettings(self): if not constants.HAS_DEV_RESOURCES: return ResMgr.purge(INPUT_HANDLER_CFG) sec = ResMgr.openSection(INPUT_HANDLER_CFG) self.__dynamicCameraSettings = DynamicCameraSettings(sec['dynamicCameraCommon']) try: self.__ctrls['sniper'].camera.aimingSystem.reloadConfig(sec['sniperMode']['camera']) except Exception: pass def _readCfg(self): sec = ResMgr.openSection(INPUT_HANDLER_CFG) if sec is None: LOG_ERROR('can not open <%s>.' % INPUT_HANDLER_CFG) return else: self.__checkSections(sec) keySec = sec['keys'] if keySec is not None: self.__showMarkersKey = getattr(Keys, keySec.readString('showMarkersKey', ''), None) self.__alwaysShowAimKey = getattr(Keys, keySec.readString('alwaysShowAimKey', ''), None) self.__dynamicCameraSettings = DynamicCameraSettings(sec['dynamicCameraCommon']) return sec def __setupCtrls(self, section): bonusType = BigWorld.player().arenaBonusType bonusTypeCtrlsMap = _OVERWRITE_CTRLS_DESC_MAP.get(bonusType, {}) for name, desc in _CTRLS_DESC_MAP.items(): if bonusTypeCtrlsMap.has_key(name): desc = bonusTypeCtrlsMap.get(name) try: if desc[2] != _CTRL_TYPE.DEVELOPMENT or desc[2] == _CTRL_TYPE.DEVELOPMENT and constants.HAS_DEV_RESOURCES: if name not in self.__ctrls: for module in _CTRL_MODULES: classType = getattr(module, desc[0], None) if classType is None: pass self.__ctrls[name] = classType(section[desc[1]] if desc[1] else None, self) break except Exception: LOG_DEBUG('Error while setting ctrls', name, desc, constants.HAS_DEV_RESOURCES) LOG_CURRENT_EXCEPTION() return def __checkSections(self, section): for _, desc in _CTRLS_DESC_MAP.items(): if desc[1] is None or desc[2] == _CTRL_TYPE.OPTIONAL or desc[2] == _CTRL_TYPE.DEVELOPMENT and not constants.HAS_DEV_RESOURCES: continue if not section.has_key(desc[1]): LOG_ERROR('Invalid section <%s> in <%s>.' % (desc[1], INPUT_HANDLER_CFG)) return def __onArenaStarted(self, period, *args): self.__isArenaStarted = period == ARENA_PERIOD.BATTLE self.__curCtrl.setGunMarkerFlag(self.__isArenaStarted, _GUN_MARKER_FLAG.CONTROL_ENABLED) self.showGunMarker2(gun_marker_ctrl.useServerGunMarker()) self.showGunMarker(gun_marker_ctrl.useClientGunMarker()) def __onRecreateDevice(self): self.__curCtrl.onRecreateDevice() self.__targeting.onRecreateDevice() def __onSettingsChanged(self, diff): if 'dynamicCamera' in diff or 'horStabilizationSnp' in diff: dynamicCamera = self.settingsCore.getSetting('dynamicCamera') horStabilizationSnp = self.settingsCore.getSetting('horStabilizationSnp') self.enableDynamicCamera(dynamicCamera, horStabilizationSnp) def __onRequestFail(self): player = BigWorld.player() if player is not None: player.showVehicleError('cantSwitchEngineDestroyed') return
class DetachedTurret(BigWorld.Entity, ScriptGameObject): allTurrets = list() collisions = ComponentDescriptor() def __init__(self): ScriptGameObject.__init__(self, self.spaceID) self.__vehDescr = vehicles.VehicleDescr( compactDescr=self.vehicleCompDescr) self.filter = BigWorld.WGTurretFilter() self.__detachConfirmationTimer = SynchronousDetachment(self) self.__detachConfirmationTimer.onInit() self.__detachmentEffects = None self.targetFullBounds = True self.targetCaps = [1] self.__isBeingPulledCallback = None self.__hitEffects = None self.__vehicleStickers = None return def reload(self): pass def __prepareModelAssembler(self): LOG_DEBUG('__prepareModelAssembler', self.__vehDescr.name, self.spaceID) assembler = BigWorld.CompoundAssembler(self.__vehDescr.name, self.spaceID) turretModel, gunModel = self.__getModels() assembler.addRootPart(turretModel, TankPartNames.TURRET) assembler.emplacePart(gunModel, TankNodeNames.GUN_JOINT, TankPartNames.GUN) bspModels = ((TankPartNames.getIdx(TankPartNames.TURRET), self.__vehDescr.turret.hitTester.bspModelName), (TankPartNames.getIdx(TankPartNames.GUN), self.__vehDescr.gun.hitTester.bspModelName)) collisionAssembler = BigWorld.CollisionAssembler( bspModels, BigWorld.player().spaceID) return [assembler, collisionAssembler] def __getModels(self): outfit = prepareBattleOutfit(self.outfitCD, self.__vehDescr, self.vehicleID) style = outfit.style if style is None: return (self.__vehDescr.turret.models.exploded, self.__vehDescr.gun.models.exploded) else: modelsSetParams = ModelsSetParams(style.modelsSet, ModelStates.EXPLODED, []) _, _, turretModel, gunModel = getPartModelsFromDesc( self.__vehDescr, modelsSetParams) return (turretModel, gunModel) def prerequisites(self): LOG_DEBUG('prerequisites') prereqs = self.__prepareModelAssembler() prereqs += self.__vehDescr.prerequisites() return prereqs def onEnterWorld(self, prereqs): LOG_DEBUG('onEnterWorld', self.__vehDescr.name, self.spaceID) self.model = prereqs[self.__vehDescr.name] self.model.matrix = self.matrix self.collisions = prereqs['collisionAssembler'] self.__detachConfirmationTimer.onEnterWorld() self.__vehDescr.keepPrereqs(prereqs) turretDescr = self.__vehDescr.turret if self.isUnderWater == 0: self.__detachmentEffects = _TurretDetachmentEffects( self.model, turretDescr.turretDetachmentEffects, self.isCollidingWithWorld == 1) self.addComponent(self.__detachmentEffects) else: self.__detachmentEffects = None self.__hitEffects = _HitEffects(self.model) self.addComponent(self.__hitEffects) self.__componentsDesc = (self.__vehDescr.turret, self.__vehDescr.gun) from helpers.CallbackDelayer import CallbackDelayer self.__isBeingPulledCallback = CallbackDelayer() self.__isBeingPulledCallback.delayCallback(self.__checkIsBeingPulled(), self.__checkIsBeingPulled) DetachedTurret.allTurrets.append(self) collisionData = ((TankPartNames.getIdx(TankPartNames.TURRET), self.model.matrix), (TankPartNames.getIdx(TankPartNames.GUN), self.model.node(TankPartNames.GUN))) self.collisions.connect(self.id, ColliderTypes.DYNAMIC_COLLIDER, collisionData) ScriptGameObject.activate(self) return def isAlive(self): return False def removeEdge(self): pass def drawEdge(self): pass def __createAndAttachStickers(self): vehicle = BigWorld.entity(self.vehicleID) if not vehicle: return if self.__vehicleStickers: return self.__vehicleStickers = VehicleStickers( self.__vehDescr, vehicle.publicInfo['marksOnGun']) self.__vehicleStickers.alpha = vehicles.g_cache.commonConfig[ 'miscParams']['damageStickerAlpha'] self.__vehicleStickers.attach(self.model, True, False, True) def onLeaveWorld(self): LOG_DEBUG('onLeaveWorld') ScriptGameObject.deactivate(self) ScriptGameObject.destroy(self) DetachedTurret.allTurrets.remove(self) self.__detachConfirmationTimer.cancel() self.__detachConfirmationTimer = None self.__isBeingPulledCallback.destroy() self.__isBeingPulledCallback = None if self.__vehicleStickers is not None: self.__vehicleStickers.detach() self.__vehicleStickers = None return def onStaticCollision(self, energy, point, normal): if self.__detachmentEffects is not None: surfaceMaterial = calcSurfaceMaterialNearPoint( point, normal, self.spaceID) effectIdx = surfaceMaterial.effectIdx groundEffect = True distToWater = BigWorld.wg_collideWater(self.position, surfaceMaterial.point) collisionPointDest = surfaceMaterial.point - self.position if distToWater != -1 and distToWater <= collisionPointDest.length: vel = Math.Vector3(self.velocity).length if vel < _MIN_COLLISION_SPEED: groundEffect = False effectIdx = material_kinds.EFFECT_MATERIAL_INDEXES_BY_NAMES[ 'water'] self.__detachmentEffects.notifyAboutCollision( energy, point, effectIdx, groundEffect, self.isUnderWater) return def showDamageFromShot(self, points, effectsIndex): _, decodedPoints, _ = DamageFromShotDecoder.decodeHitPoints( points, self.collisions) for shotPoint in decodedPoints: if shotPoint.componentName == TankPartNames.TURRET or shotPoint.componentName == TankPartNames.GUN: self.__hitEffects.showHit(shotPoint, effectsIndex, shotPoint.componentName) LOG_ERROR( "Detached turret got hit into %s component, but it's impossible" % shotPoint.componentName) def set_isUnderWater(self, prev): if self.__detachmentEffects is not None: if self.isUnderWater: self.__detachmentEffects.stopEffects() return def set_isCollidingWithWorld(self, prev): pass def changeAppearanceVisibility(self, isVisible): self.model.visible = isVisible def __checkIsBeingPulled(self): if self.__detachmentEffects is not None: if self.isCollidingWithWorld and not self.isUnderWater and self.velocity.lengthSquared > 0.1: extent = Math.Matrix( self.model.getBoundsForRoot()).applyVector( Math.Vector3(0.5, 0.5, 0.5)).length surfaceMaterial = calcSurfaceMaterialNearPoint( self.position, Math.Vector3(0, extent, 0), self.spaceID) self.__detachmentEffects.notifyAboutBeingPulled( True, surfaceMaterial.effectIdx) if surfaceMaterial.matKind == 0: LOG_ERROR( 'calcSurfaceMaterialNearPoint failed to find the collision point at: ', self.position) else: self.__detachmentEffects.notifyAboutBeingPulled(False, None) return SERVER_TICK_LENGTH
class CommonTankAppearance(ScriptGameObject): compoundModel = property(lambda self: self._compoundModel) boundEffects = property(lambda self: self.__boundEffects) fashions = property(lambda self: self.__fashions) 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) outfit = property(lambda self: self.__outfit) renderState = property(lambda self: self.__renderState) def _setFashions(self, fashions, isTurretDetached=False): self.__fashions = fashions if isTurretDetached: self.compoundModel.setupFashions((fashions.chassis, fashions.hull)) else: self.compoundModel.setupFashions(fashions) terrainMatKind = property(lambda self: self.__currTerrainMatKind) terrainGroundType = property(lambda self: self.__currTerrainGroundType) 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) modelsSetParams = property(lambda self: ModelsSetParams(self.outfit.modelsSet, self.damageState.modelState, self.__attachments)) splineTracks = property(lambda self: self._splineTracks) 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) trackScrollController = property(lambda self: self.__trackScrollCtl) wheelsState = property(lambda self: 0) burnoutLevel = property(lambda self: 0.0) filterRetrievers = property(lambda self: self.__filterRetrievers) allLodCalculators = property(lambda self: self.__allLodCalculators) transmissionSlip = property(lambda self: self._commonSlip) transmissionScroll = property(lambda self: self._commonScroll) vehicleStickers = property(lambda self: self._vehicleStickers) isTurretDetached = property(lambda self: self._isTurretDetached) _weaponEnergy = property(lambda self: self.__weaponEnergy) filter = AutoProperty() areaTriggerTarget = ComponentDescriptor() burnoutProcessor = ComponentDescriptor() c11nComponent = ComponentDescriptor() collisionObstaclesCollector = ComponentDescriptor() collisions = ComponentDescriptor() crashedTracksController = ComponentDescriptor() customEffectManager = ComponentDescriptor() detailedEngineState = ComponentDescriptor() dirtComponent = ComponentDescriptor() engineAudition = ComponentDescriptor() flyingInfoProvider = ComponentDescriptor() frictionAudition = ComponentDescriptor() gearbox = ComponentDescriptor() gunLinkedNodesAnimator = ComponentDescriptor() gunRecoil = ComponentDescriptor() gunAnimators = [ComponentDescriptor()] gunRotatorAudition = ComponentDescriptor() hullAimingController = ComponentDescriptor() leveredSuspension = ComponentDescriptor() lodCalculator = ComponentDescriptor() shadowManager = ComponentDescriptor() siegeEffects = ComponentDescriptor() suspension = ComponentDescriptor() suspensionSound = ComponentDescriptor() swingingAnimator = ComponentDescriptor() terrainMatKindSensor = ComponentDescriptor() tessellationCollisionSensor = ComponentDescriptor() trackNodesAnimator = ComponentDescriptor() tracks = ComponentDescriptor() transform = ComponentDescriptor() vehicleTraces = ComponentDescriptor() waterSensor = ComponentDescriptor() wheeledLodCalculator = ComponentDescriptor() wheelsAnimator = ComponentDescriptor() flagComponent = ComponentDescriptor() def __init__(self, spaceID): ScriptGameObject.__init__(self, spaceID) self._vehicle = None self.__filter = None self.__typeDesc = None self.crashedTracksController = None self.__currentDamageState = VehicleDamageState() self.__currTerrainMatKind = [-1] * MATKIND_COUNT self.__currTerrainGroundType = [-1] * MATKIND_COUNT self.__terrainEffectMaterialNames = [''] * MATKIND_COUNT self._chassisDecal = VehicleDecal(self) self.__splodge = None self.__boundEffects = None self._splineTracks = None self.flyingInfoProvider = self.createComponent(Vehicular.FlyingInfoProvider) self.__trackScrollCtl = BigWorld.PyTrackScroll() self.__trackScrollCtl.setFlyingInfo(DataLinks.createBoolLink(self.flyingInfoProvider, 'isLeftSideFlying'), DataLinks.createBoolLink(self.flyingInfoProvider, 'isRightSideFlying')) self.__weaponEnergy = 0.0 self.__outfit = None self.__systemStarted = False self.__isAlive = True self._isTurretDetached = False self.__isObserver = False self.__attachments = [] self.__modelAnimators = [] self.turretMatrix = None self.gunMatrix = None self.__allLodCalculators = [] self._commonScroll = 0.0 self._commonSlip = 0.0 self._compoundModel = None self.__fashions = None self.__filterRetrievers = [] self._vehicleStickers = None self.__vID = 0 self.__renderState = None self.__frameTimestamp = 0 self.__periodicTimerID = None return def prerequisites(self, typeDescriptor, vID, health, isCrewActive, isTurretDetached, outfitCD, renderState=None): self.damageState.update(health, isCrewActive, False) self.__typeDesc = typeDescriptor self.__vID = vID self._isTurretDetached = isTurretDetached self.__outfit = self._prepareOutfit(outfitCD) if self.damageState.isCurrentModelUndamaged: self.__attachments = camouflages.getAttachments(self.outfit, self.typeDescriptor) self.__renderState = renderState prereqs = self.typeDescriptor.prerequisites(True) prereqs.extend(camouflages.getCamoPrereqs(self.outfit, self.typeDescriptor)) prereqs.extend(camouflages.getModelAnimatorsPrereqs(self.outfit, self.worldID)) prereqs.extend(camouflages.getAttachmentsAnimatorsPrereqs(self.__attachments, self.worldID)) splineDesc = self.typeDescriptor.chassis.splineDesc if splineDesc is not None: modelsSet = self.outfit.modelsSet prereqs.append(splineDesc.segmentModelLeft(modelsSet)) prereqs.append(splineDesc.segmentModelRight(modelsSet)) segment2ModelLeft = splineDesc.segment2ModelLeft(modelsSet) if segment2ModelLeft is not None: prereqs.append(segment2ModelLeft) segment2ModelRight = splineDesc.segment2ModelRight(modelsSet) if segment2ModelRight is not None: prereqs.append(segment2ModelRight) modelsSetParams = self.modelsSetParams compoundAssembler = model_assembler.prepareCompoundAssembler(self.typeDescriptor, modelsSetParams, self.worldID, self.isTurretDetached, renderState=self.renderState) prereqs.append(compoundAssembler) if renderState == RenderStates.OVERLAY_COLLISION: self.damageState.update(0, isCrewActive, False) if not isTurretDetached: bspModels = ((TankPartNames.getIdx(TankPartNames.CHASSIS), typeDescriptor.chassis.hitTester.bspModelName), (TankPartNames.getIdx(TankPartNames.HULL), typeDescriptor.hull.hitTester.bspModelName), (TankPartNames.getIdx(TankPartNames.TURRET), typeDescriptor.turret.hitTester.bspModelName), (TankPartNames.getIdx(TankPartNames.GUN), typeDescriptor.gun.hitTester.bspModelName)) else: bspModels = ((TankPartNames.getIdx(TankPartNames.CHASSIS), typeDescriptor.chassis.hitTester.bspModelName), (TankPartNames.getIdx(TankPartNames.HULL), typeDescriptor.hull.hitTester.bspModelName)) collisionAssembler = BigWorld.CollisionAssembler(bspModels, self.worldID) prereqs.append(collisionAssembler) physicalTracksBuilders = self.typeDescriptor.chassis.physicalTracks for name, builders in physicalTracksBuilders.iteritems(): for index, builder in enumerate(builders): prereqs.append(builder.createLoader(self.worldID, '{0}{1}PhysicalTrack'.format(name, index), modelsSetParams.skin)) return prereqs def construct(self, isPlayer, resourceRefs): self.collisions = resourceRefs['collisionAssembler'] self.typeDescriptor.chassis.hitTester.bbox = self.collisions.getBoundingBox(TankPartNames.getIdx(TankPartNames.CHASSIS)) self.typeDescriptor.hull.hitTester.bbox = self.collisions.getBoundingBox(TankPartNames.getIdx(TankPartNames.HULL)) self.typeDescriptor.turret.hitTester.bbox = self.collisions.getBoundingBox(TankPartNames.getIdx(TankPartNames.TURRET)) self.typeDescriptor.gun.hitTester.bbox = self.collisions.getBoundingBox(TankPartNames.getIdx(TankPartNames.GUN)) self.__isObserver = 'observer' in self.typeDescriptor.type.tags self._compoundModel = resourceRefs[self.typeDescriptor.name] self.__boundEffects = bound_effects.ModelBoundEffects(self.compoundModel) isCurrentModelDamaged = self.damageState.isCurrentModelDamaged fashions = camouflages.prepareFashions(isCurrentModelDamaged) if not isCurrentModelDamaged: model_assembler.setupTracksFashion(self.typeDescriptor, fashions.chassis) self._setFashions(fashions, self.isTurretDetached) self._setupModels() if not isCurrentModelDamaged: modelsSet = self.outfit.modelsSet self._splineTracks = model_assembler.setupSplineTracks(self.fashion, self.typeDescriptor, self.compoundModel, resourceRefs, modelsSet) self.crashedTracksController = CrashedTrackController(self.typeDescriptor, self.fashion, modelsSet) else: self.__trackScrollCtl = None self._chassisDecal.create() self.__modelAnimators = camouflages.getModelAnimators(self.outfit, self.typeDescriptor, self.worldID, resourceRefs, self.compoundModel) if self.modelsSetParams.state == 'undamaged': self.__modelAnimators.extend(camouflages.getAttachmentsAnimators(self.__attachments, self.worldID, resourceRefs, self.compoundModel)) self.transform = self.createComponent(GenericComponents.TransformComponent, Math.Vector3(0, 0, 0)) self.areaTriggerTarget = self.createComponent(Triggers.AreaTriggerTarget) self.__filter = model_assembler.createVehicleFilter(self.typeDescriptor) compoundModel = self.compoundModel if self.isAlive: self.detailedEngineState, self.gearbox = model_assembler.assembleDrivetrain(self, isPlayer) if not gEffectsDisabled(): self.customEffectManager = CustomEffectManager(self) if self.typeDescriptor.hasSiegeMode: self.siegeEffects = SiegeEffectsController(self, isPlayer) model_assembler.assembleVehicleAudition(isPlayer, self) self.detailedEngineState.onEngineStart = self._onEngineStart self.detailedEngineState.onStateChanged = self.engineAudition.onEngineStateChanged if isPlayer: turret = self.typeDescriptor.turret gunRotatorAudition = self.createComponent(Vehicular.GunRotatorAudition, turret.turretRotatorSoundManual, turret.weight / 1000.0, compoundModel.node(TankPartNames.TURRET)) gunRotatorAudition.vehicleMatrixLink = self.compoundModel.root gunRotatorAudition.damaged = lambda : self.turretDamaged() gunRotatorAudition.maxTurretRotationSpeed = lambda : self.maxTurretRotationSpeed() self.gunRotatorAudition = gunRotatorAudition self.frictionAudition = self.createComponent(Vehicular.FrictionAudition, TANK_FRICTION_EVENT) isLodTopPriority = isPlayer lodCalcInst = self.createComponent(Vehicular.LodCalculator, DataLinks.linkMatrixTranslation(compoundModel.matrix), True, VEHICLE_PRIORITY_GROUP, isLodTopPriority) self.lodCalculator = lodCalcInst self.allLodCalculators.append(lodCalcInst) lodLink = DataLinks.createFloatLink(lodCalcInst, 'lodDistance') lodStateLink = lodCalcInst.lodStateLink if IS_EDITOR: matrixBinding = None changeCamera = None else: matrixBinding = BigWorld.player().consistentMatrices.onVehicleMatrixBindingChanged changeCamera = BigWorld.player().inputHandler.onCameraChanged self.shadowManager = VehicleShadowManager(compoundModel, matrixBinding, changeCamera) if not self.damageState.isCurrentModelDamaged: self.__assembleNonDamagedOnly(resourceRefs, isPlayer, lodLink, lodStateLink) dirtEnabled = BigWorld.WG_dirtEnabled() and 'HD' in self.typeDescriptor.type.tags if dirtEnabled and self.fashions is not None: dirtHandlers = [BigWorld.PyDirtHandler(True, compoundModel.node(TankPartNames.CHASSIS).position.y), BigWorld.PyDirtHandler(False, compoundModel.node(TankPartNames.HULL).position.y), BigWorld.PyDirtHandler(False, compoundModel.node(TankPartNames.TURRET).position.y), BigWorld.PyDirtHandler(False, compoundModel.node(TankPartNames.GUN).position.y)] modelHeight, _ = self.computeVehicleHeight() self.dirtComponent = self.createComponent(Vehicular.DirtComponent, dirtHandlers, modelHeight) for fashionIdx, _ in enumerate(TankPartNames.ALL): self.fashions[fashionIdx].addMaterialHandler(dirtHandlers[fashionIdx]) self.fashions[fashionIdx].addTrackMaterialHandler(dirtHandlers[fashionIdx]) model_assembler.setupTurretRotations(self) self.waterSensor = model_assembler.assembleWaterSensor(self.typeDescriptor, self, lodStateLink, self.worldID) if self.engineAudition is not None: self.engineAudition.setIsUnderwaterInfo(DataLinks.createBoolLink(self.waterSensor, 'isUnderWater')) self.engineAudition.setIsInWaterInfo(DataLinks.createBoolLink(self.waterSensor, 'isInWater')) self.__postSetupFilter() compoundModel.setPartBoundingBoxAttachNode(TankPartIndexes.GUN, TankNodeNames.GUN_INCLINATION) camouflages.updateFashions(self) model_assembler.assembleCustomLogicComponents(self, self.__attachments, self.__modelAnimators) return def destroy(self): self.flagComponent = None self.__modelAnimators = [] self._destroySystems() fashions = VehiclePartsTuple(None, None, None, None) self._setFashions(fashions, self._isTurretDetached) super(CommonTankAppearance, self).destroy() self.__typeDesc = None if self.boundEffects is not None: self.boundEffects.destroy() self._vehicleStickers = None self._chassisDecal.destroy() self._chassisDecal = None self._compoundModel = None return def activate(self): if self.collisions is not None and self.isTurretDetached: self.collisions.removeAttachment(TankPartNames.getIdx(TankPartNames.TURRET)) self.collisions.removeAttachment(TankPartNames.getIdx(TankPartNames.GUN)) super(CommonTankAppearance, self).activate() if not self.isObserver: self._chassisDecal.attach() self._createAndAttachStickers() if not self.isObserver: if not self.damageState.isCurrentModelDamaged and not self.__systemStarted: self._startSystems() self.filter.enableLagDetection(not self.damageState.isCurrentModelDamaged) if self.__periodicTimerID is not None: BigWorld.cancelCallback(self.__periodicTimerID) self.__periodicTimerID = BigWorld.callback(PERIODIC_UPDATE_TIME, self.__onPeriodicTimer) self.setupGunMatrixTargets(self.filter) for lodCalculator in self.allLodCalculators: lodCalculator.setupPosition(DataLinks.linkMatrixTranslation(self.compoundModel.matrix)) for modelAnimator in self.__modelAnimators: modelAnimator.animator.start() 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.isObserver: self.compoundModel.visible = False if self.collisions is not None: chassisColisionMatrix, gunNodeName = self._vehicleColliderInfo collisionData = ((TankPartNames.getIdx(TankPartNames.HULL), self.compoundModel.node(TankPartNames.HULL)), (TankPartNames.getIdx(TankPartNames.TURRET), self.compoundModel.node(TankPartNames.TURRET)), (TankPartNames.getIdx(TankPartNames.CHASSIS), chassisColisionMatrix), (TankPartNames.getIdx(TankPartNames.GUN), self.compoundModel.node(gunNodeName))) self.collisions.connect(self.id, ColliderTypes.VEHICLE_COLLIDER, collisionData) return def deactivate(self): for modelAnimator in self.__modelAnimators: modelAnimator.animator.stop() if self.damageState and self.damageState.isCurrentModelDamaged: self.__modelAnimators = [] self.shadowManager.unregisterCompoundModel(self.compoundModel) if self.__systemStarted: self._stopSystems() super(CommonTankAppearance, self).deactivate() self._chassisDecal.detach() self.filter.enableLagDetection(False) if self.vehicleStickers: self.vehicleStickers.detach() def setupGunMatrixTargets(self, target): self.turretMatrix = target.turretMatrix self.gunMatrix = target.gunMatrix def receiveShotImpulse(self, direction, impulse): if not VehicleDamageState.isDamagedModel(self.damageState.modelState): self.swingingAnimator.receiveShotImpulse(direction, impulse) if self.crashedTracksController is not None: self.crashedTracksController.receiveShotImpulse(direction, impulse) return def computeVehicleHeight(self): gunLength = 0.0 height = 0.0 if self.collisions is not None: desc = self.typeDescriptor hullBB = self.collisions.getBoundingBox(TankPartNames.getIdx(TankPartNames.HULL)) turretBB = self.collisions.getBoundingBox(TankPartNames.getIdx(TankPartNames.TURRET)) gunBB = self.collisions.getBoundingBox(TankPartNames.getIdx(TankPartNames.GUN)) hullTopY = desc.chassis.hullPosition[1] + hullBB[1][1] turretTopY = desc.chassis.hullPosition[1] + desc.hull.turretPositions[0][1] + turretBB[1][1] gunTopY = desc.chassis.hullPosition[1] + desc.hull.turretPositions[0][1] + desc.turret.gunPosition[1] + gunBB[1][1] gunLength = math.fabs(gunBB[1][2] - gunBB[0][2]) height = max(hullTopY, max(turretTopY, gunTopY)) return (height, gunLength) def onWaterSplash(self, waterHitPoint, isHeavySplash): pass def onUnderWaterSwitch(self, isUnderWater): pass def getWheelsSteeringMax(self): pass def _prepareOutfit(self, outfitCD): outfitComponent = camouflages.getOutfitComponent(outfitCD) return Outfit(component=outfitComponent, vehicleCD=self.typeDescriptor.makeCompactDescr()) def _setupModels(self): self.__isAlive = not self.damageState.isCurrentModelDamaged if self.isAlive: _, gunLength = self.computeVehicleHeight() self.__weaponEnergy = gunLength * self.typeDescriptor.shot.shell.caliber if MAX_DISTANCE > 0 and not self.isObserver: transform = self.typeDescriptor.chassis.AODecals[0] splodge = BigWorld.Splodge(transform, MAX_DISTANCE, self.typeDescriptor.chassis.hullPosition.y) if splodge: self.__splodge = splodge node = self.compoundModel.node(TankPartNames.HULL) node.attach(splodge) def _createStickers(self): return VehicleStickers(self.typeDescriptor, 0, self.outfit) @property def _vehicleColliderInfo(self): chassisColisionMatrix = self.compoundModel.matrix if self.damageState.isCurrentModelDamaged: gunNodeName = 'gun' else: gunNodeName = TankNodeNames.GUN_INCLINATION return (chassisColisionMatrix, gunNodeName) def _startSystems(self): self.__systemStarted = True if self.flyingInfoProvider is not None: self.flyingInfoProvider.setData(self.filter, self.suspension) if self.trackScrollController is not None: self.trackScrollController.activate() self.trackScrollController.setData(self.filter) if self.engineAudition is not None: self.engineAudition.setWeaponEnergy(self._weaponEnergy) self.engineAudition.attachToModel(self.compoundModel) if self.hullAimingController is not None: self.hullAimingController.setData(self.filter, self.typeDescriptor) return def _stopSystems(self): self.__systemStarted = False if self.flyingInfoProvider is not None: self.flyingInfoProvider.setData(None, None) if self.trackScrollController is not None: self.trackScrollController.deactivate() self.trackScrollController.setData(None) if self.__periodicTimerID is not None: BigWorld.cancelCallback(self.__periodicTimerID) self.__periodicTimerID = None return def _destroySystems(self): self.__systemStarted = False if self.trackScrollController is not None: self.trackScrollController.deactivate() self.__trackScrollCtl = None if self.crashedTracksController is not None: self.crashedTracksController.destroy() self.crashedTracksController = None if self.__periodicTimerID is not None: BigWorld.cancelCallback(self.__periodicTimerID) self.__periodicTimerID = None return def _onRequestModelsRefresh(self): self.flagComponent = None return def _onEngineStart(self): if self.engineAudition is not None: self.engineAudition.onEngineStart() return def __assembleNonDamagedOnly(self, resourceRefs, isPlayer, lodLink, lodStateLink): model_assembler.assembleTerrainMatKindSensor(self, lodStateLink, self.worldID) model_assembler.assembleRecoil(self, lodLink) model_assembler.assembleMultiGunRecoil(self, lodLink) model_assembler.assembleGunLinkedNodesAnimator(self) model_assembler.assembleCollisionObstaclesCollector(self, lodStateLink, self.typeDescriptor, self.worldID) model_assembler.assembleTessellationCollisionSensor(self, lodStateLink) wheelsScroll = None wheelsSteering = None generalWheelsAnimatorConfig = self.typeDescriptor.chassis.generalWheelsAnimatorConfig if generalWheelsAnimatorConfig is not None: scrollableWheelsCount = generalWheelsAnimatorConfig.getNonTrackWheelsCount() wheelsScroll = [] for _ in xrange(scrollableWheelsCount): retriever = self.createComponent(NetworkFilters.FloatFilterRetriever) wheelsScroll.append(DataLinks.createFloatLink(retriever, 'value')) self.filterRetrievers.append(retriever) steerableWheelsCount = generalWheelsAnimatorConfig.getSteerableWheelsCount() wheelsSteering = [] for _ in xrange(steerableWheelsCount): retriever = self.createComponent(NetworkFilters.FloatFilterRetriever) wheelsSteering.append(DataLinks.createFloatLink(retriever, 'value')) self.filterRetrievers.append(retriever) self.wheelsAnimator = model_assembler.createWheelsAnimator(self, ColliderTypes.VEHICLE_COLLIDER, self.typeDescriptor, lambda : self.wheelsState, wheelsScroll, wheelsSteering, self.splineTracks, lodStateLink) if self.customEffectManager is not None: self.customEffectManager.setWheelsData(self) suspensionLodLink = lodStateLink if 'wheeledVehicle' in self.typeDescriptor.type.tags: wheeledLodCalculator = Vehicular.LodCalculator(self.worldID, DataLinks.linkMatrixTranslation(self.compoundModel.matrix), True, WHEELED_CHASSIS_PRIORITY_GROUP, isPlayer) self.wheeledLodCalculator = wheeledLodCalculator self.allLodCalculators.append(wheeledLodCalculator) suspensionLodLink = wheeledLodCalculator.lodStateLink model_assembler.assembleSuspensionIfNeed(self, suspensionLodLink) model_assembler.assembleLeveredSuspensionIfNeed(self, suspensionLodLink) self.__assembleSwinging(lodLink) model_assembler.assembleBurnoutProcessor(self) model_assembler.assembleSuspensionSound(self, lodLink, isPlayer) model_assembler.assembleHullAimingController(self) self.trackNodesAnimator = model_assembler.createTrackNodesAnimator(self, self.typeDescriptor, lodStateLink) model_assembler.assembleTracks(resourceRefs, self.typeDescriptor, self, self.splineTracks, False, lodStateLink) model_assembler.assembleVehicleTraces(self, self.filter, lodStateLink) return def __assembleSwinging(self, lodLink): self.swingingAnimator = model_assembler.createSwingingAnimator(self, self.typeDescriptor, self.compoundModel.node(TankPartNames.HULL).localMatrix, self.compoundModel.matrix, lodLink) self.compoundModel.node(TankPartNames.HULL, self.swingingAnimator.animatedMProv) if hasattr(self.filter, 'placingCompensationMatrix'): self.swingingAnimator.placingCompensationMatrix = self.filter.placingCompensationMatrix def __postSetupFilter(self): suspensionWorking = self.suspension is not None and self.suspension.hasGroundNodes placingOnGround = not (suspensionWorking or self.leveredSuspension is not None) self.filter.placingOnGround = placingOnGround return def _createAndAttachStickers(self): isCurrentModelDamaged = self.damageState.isCurrentModelDamaged stickersAlpha = DEFAULT_STICKERS_ALPHA if isCurrentModelDamaged: stickersAlpha = items.vehicles.g_cache.commonConfig['miscParams']['damageStickerAlpha'] if self.vehicleStickers is None: self._vehicleStickers = self._createStickers() self.vehicleStickers.alpha = stickersAlpha self.vehicleStickers.attach(compoundModel=self.compoundModel, isDamaged=self.damageState.isCurrentModelDamaged, showDamageStickers=not isCurrentModelDamaged) return def __onPeriodicTimer(self): timeStamp = BigWorld.wg_getFrameTimestamp() if self.__frameTimestamp >= timeStamp: self.__periodicTimerID = BigWorld.callback(0.0, self.__onPeriodicTimer) else: self.__frameTimestamp = timeStamp self.__periodicTimerID = BigWorld.callback(PERIODIC_UPDATE_TIME, self.__onPeriodicTimer) self._periodicUpdate() def _periodicUpdate(self): if self._vehicle is None or not self._vehicle.isAlive(): return else: self._updateCurrTerrainMatKinds() self.__updateEffectsLOD() if self.customEffectManager: self.customEffectManager.update() return def __updateEffectsLOD(self): if self.customEffectManager: distanceFromPlayer = self.lodCalculator.lodDistance 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 _stopEffects(self): self.boundEffects.stop() 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) args = dict(isPlayerVehicle=vehicle.isPlayerVehicle, showShockWave=vehicle.isPlayerVehicle, showFlashBang=vehicle.isPlayerVehicle, entity_id=vehicle.id, 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)) if isSpawnedBot(self.typeDescriptor.type.tags) and kind in ('explosion', 'destruction'): player = BigWorld.player() if player is not None and isPlayerAvatar(): player.terrainEffects.addNew(self._vehicle.position, effects[1], effects[0], None, **args) else: self.boundEffects.addNew(None, effects[1], effects[0], **args) return def _updateCurrTerrainMatKinds(self): if self.terrainMatKindSensor is None: return else: matKinds = self.terrainMatKindSensor.matKinds groundTypes = self.terrainMatKindSensor.groundTypes materialsCount = len(matKinds) for i in xrange(MATKIND_COUNT): matKind = matKinds[i] if i < materialsCount else 0 groundType = groundTypes[i] if i < materialsCount else 0 self.terrainMatKind[i] = matKind self.terrainGroundType[i] = groundType 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.terrainMatKind[0], self.terrainMatKind[1]) return def changeEngineMode(self, mode, forceSwinging=False): if self.detailedEngineState is not None: self.detailedEngineState.mode = mode[0] if self.trackScrollController is not None: self.trackScrollController.setMode(mode) return def changeSiegeState(self, siegeState): if self.engineAudition is not None: self.engineAudition.onSiegeStateChanged(siegeState) return def turretDamaged(self): pass def maxTurretRotationSpeed(self): pass
class CompoundAppearance(CommonTankAppearance, CallbackDelayer): activated = property(lambda self: self.__activated) wheelsState = property(lambda self: self._vehicle.wheelsState if self._vehicle is not None else 0) wheelsSteering = property(lambda self: self._vehicle.wheelsSteeringSmoothed if self._vehicle is not None else None) wheelsScroll = property(lambda self: self._vehicle.wheelsScrollSmoothed if self._vehicle is not None else None) burnoutLevel = property(lambda self: self._vehicle.burnoutLevel / 255.0 if self._vehicle is not None else 0.0) isConstructed = property(lambda self: self.__isConstructed) highlighter = ComponentDescriptor() peripheralsController = ComponentDescriptor() tutorialMatKindsController = ComponentDescriptor() def __init__(self): CallbackDelayer.__init__(self) CommonTankAppearance.__init__(self, BigWorld.player().spaceID) self.turretMatrix = Math.WGAdaptiveMatrixProvider() self.gunMatrix = Math.WGAdaptiveMatrixProvider() self.__originalFilter = None self.__terrainCircle = None self.onModelChanged = Event() self.__activated = False self.__dirtUpdateTime = 0.0 self.__inSpeedTreeCollision = False self.__isConstructed = False self.__tmpGameObjectNames = [] return def setVehicle(self, vehicle): self._vehicle = vehicle if self.customEffectManager is not None: self.customEffectManager.setVehicle(vehicle) if self.crashedTracksController is not None: self.crashedTracksController.setVehicle(vehicle) if self.frictionAudition is not None: self.frictionAudition.setVehicleMatrix(vehicle.matrix) self.highlighter.setVehicle(vehicle) self.__applyVehicleOutfit() fstList = vehicle.wheelsScrollFilters if vehicle.wheelsScrollFilters else [] scndList = vehicle.wheelsSteeringFilters if vehicle.wheelsSteeringFilters else [] for retriever, floatFilter in zip(self.filterRetrievers, fstList + scndList): retriever.setupFilter(floatFilter) self.transform.translation = Math.Matrix(vehicle.matrix).translation self.createComponent(NetworkComponents.NetworkEntity, vehicle) self.createComponent(NetworkComponents.EntityTransformSyncer) return def getVehicle(self): return self._vehicle 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 @property def _vehicleColliderInfo(self): if self.damageState.isCurrentModelDamaged: chassisCollisionMatrix = self.compoundModel.matrix gunNodeName = 'gun' else: chassisCollisionMatrix = self._vehicle.filter.groundPlacingMatrix gunNodeName = TankNodeNames.GUN_INCLINATION return (chassisCollisionMatrix, gunNodeName) def activate(self): if self.__activated or self._vehicle is None: return else: isPlayerVehicle = self._vehicle.isPlayerVehicle 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 if isPlayerVehicle and self.collisions is not None: colliderData = (self.collisions.getColliderID(), (TankPartNames.getIdx(TankPartNames.HULL), TankPartNames.getIdx(TankPartNames.TURRET), TankPartNames.getIdx(TankPartNames.GUN))) BigWorld.appendCameraCollider(colliderData) self.__inSpeedTreeCollision = True BigWorld.setSpeedTreeCollisionBody( self.compoundModel.getBoundsForPart(TankPartIndexes.HULL)) self.__linkCompound() self.__createTerrainCircle() super(CompoundAppearance, self).activate() self.onModelChanged() if not self.isObserver: self.__dirtUpdateTime = BigWorld.time() 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.highlighter.removeHighlight() super(CompoundAppearance, self).deactivate() if self.__inSpeedTreeCollision: BigWorld.setSpeedTreeCollisionBody(None) if self.collisions is not None: BigWorld.removeCameraCollider(self.collisions.getColliderID()) self.turretMatrix.target = None self.gunMatrix.target = None self._vehicle.filter = self.__originalFilter self.filter.reset() self.__originalFilter = None if self.__terrainCircle.isAttached(): self.__terrainCircle.detach() if stopEffects: self._stopEffects() self._vehicle.model = None self.compoundModel.matrix = Math.Matrix() self._vehicle = None BigWorld.player().arena.onPeriodChange -= self.__arenaPeriodChanged BigWorld.player( ).inputHandler.onCameraChanged -= self.__onCameraChanged return def _startSystems(self): super(CompoundAppearance, self)._startSystems() if self._vehicle.isPlayerVehicle: self.delayCallback(_PERIODIC_TIME_ENGINE, self.__onPeriodicTimerEngine) self.highlighter.highlight(True) if self.peripheralsController is not None: self.peripheralsController.attachToVehicle(self._vehicle) if self.detailedEngineState is not None: self.detailedEngineState.onGearUpCbk = self.__onEngineStateGearUp self.delayCallback(_PERIODIC_TIME_DIRT[0][0], self.__onPeriodicTimerDirt) return def _stopSystems(self): super(CompoundAppearance, self)._stopSystems() if self._vehicle.isPlayerVehicle: self.highlighter.highlight(False) self.stopCallback(self.__onPeriodicTimerEngine) self.stopCallback(self.__onPeriodicTimerDirt) def _onEngineStart(self): super(CompoundAppearance, self)._onEngineStart() hasTurbocharger = False if self._vehicle is not None: for device in self.getVehicle().getOptionalDevices(): if device is not None and device.groupName == 'turbocharger': hasTurbocharger = True if hasTurbocharger and self.engineAudition is not None: engineSoundObject = self.engineAudition.getSoundObject( TankSoundObjectsIndexes.ENGINE) engineSoundObject.play('cons_turbine') return def __destroyEngineAudition(self): self.engineAudition = None if self.detailedEngineState is not None: self.detailedEngineState.onEngineStart = None self.detailedEngineState.onStateChanged = None return def __processPostmortemComponents(self): if self.wheelsAnimator is not None and self.wheelsAnimator.activePostmortem: self.wheelsAnimator.reattachToCrash(self.compoundModel, self.fashion) if self.suspension is not None and self.suspension.activePostmortem: self.suspension.reattachCompound(self.compoundModel) if self.leveredSuspension is not None and self.leveredSuspension.activePostmortem: self.leveredSuspension.reattachCompound(self.compoundModel) if self.vehicleTraces is not None and self.vehicleTraces.activePostmortem: self.vehicleTraces.setCompound(self.compoundModel) if self.collisionObstaclesCollector is not None and self.collisionObstaclesCollector.activePostmortem: self.collisionObstaclesCollector.reattachCompound( self.compoundModel) if self.tessellationCollisionSensor is not None and self.tessellationCollisionSensor.activePostmortem: self.tessellationCollisionSensor.reattachCompound( self.compoundModel) return def __prepareSystemsForDamagedVehicle(self, vehicle, isTurretDetached): if self.flyingInfoProvider is not None: self.flyingInfoProvider.setData(vehicle.filter, None) if self.vehicleTraces is not None and not self.vehicleTraces.activePostmortem: self.vehicleTraces = None self.suspensionSound = None self.swingingAnimator = None self.burnoutProcessor = None self.gunRecoil = None self.gunAnimators = [] self.gunLinkedNodesAnimator = None if self.suspension is not None and not self.suspension.activePostmortem: self.suspension = None if self.leveredSuspension is not None and not self.leveredSuspension.activePostmortem: self.leveredSuspension = None self.trackNodesAnimator = None if self.wheelsAnimator is not None and not self.wheelsAnimator.activePostmortem: self.wheelsAnimator = None self.gearbox = None self.gunRotatorAudition = None while self.__tmpGameObjectNames: tmpName = self.__tmpGameObjectNames.pop() tmpCmp = self.findComponent(tmpName) if tmpCmp: self.removeComponent(tmpCmp) _logger.warning('Component "%s" has not been found', tmpName) fashions = VehiclePartsTuple(BigWorld.WGVehicleFashion(), None, None, None) self._setFashions(fashions, isTurretDetached) model_assembler.setupTracksFashion(self.typeDescriptor, self.fashion) self.showStickers(False) self.customEffectManager = None self.__destroyEngineAudition() self.detailedEngineState = None self.frictionAudition = None self.terrainMatKindSensor = None self._splineTracks = None model = self.compoundModel self.waterSensor.sensorPlaneLink = model.root self.peripheralsController = None self.dirtComponent = None self.tracks = None if self.collisionObstaclesCollector is not None and not self.collisionObstaclesCollector.activePostmortem: self.collisionObstaclesCollector = None if self.tessellationCollisionSensor is not None and not self.tessellationCollisionSensor.activePostmortem: self.tessellationCollisionSensor = None self.siegeEffects = None self._destroySystems() return def destroy(self): if self._vehicle is not None: self.deactivate() super(CompoundAppearance, self).destroy() if self.fashion is not None: self.fashion.removePhysicalTracks() if self.__terrainCircle is not None: self.__terrainCircle.destroy() self.__terrainCircle = None self.onModelChanged.clear() self.onModelChanged = None CallbackDelayer.destroy(self) return def construct(self, isPlayer, resourceRefs): super(CompoundAppearance, self).construct(isPlayer, resourceRefs) if self.damageState.effect is not None: self.playEffect(self.damageState.effect, SpecialKeyPointNames.STATIC) if self.isAlive and isPlayer: self.peripheralsController = PeripheralsController() self.highlighter = Highlighter(self.isAlive) if isPlayer and BigWorld.player().isInTutorial: self.tutorialMatKindsController = TutorialMatKindsController() self.tutorialMatKindsController.terrainGroundTypesLink = lambda: self.terrainGroundType self.__isConstructed = True return def addTempGameObject(self, component, name): if name in self.__tmpGameObjectNames: _logger.warning('Attempt to add existed Game Object %s', name) else: self.__tmpGameObjectNames.append(name) self.addComponent(component, name) def removeTempGameObject(self, name): if name in self.__tmpGameObjectNames: self.__tmpGameObjectNames.remove(name) tmpCmp = self.findComponent(name) if tmpCmp: self.removeComponent(name) return _logger.warning('Component "%s" has not been found', name) def showStickers(self, show): self.vehicleStickers.show = show def showTerrainCircle(self, radius=None, terrainCircleSettings=None): if (radius is None) != (terrainCircleSettings is None): LOG_ERROR( 'showTerrainCircle: radius or terrainCircleSetting is not set. You need to set both or none of them.' ) return else: if radius is not None: self.__terrainCircle.configure(radius, terrainCircleSettings) if not self.__terrainCircle.isAttached(): self.__attachTerrainCircle() self.__terrainCircle.setVisible() return def hideTerrainCircle(self): self.__terrainCircle.setVisible(False) def updateTurretVisibility(self): self.__requestModelsRefresh() def changeVisibility(self, modelVisible): self.compoundModel.visible = modelVisible self.showStickers(modelVisible) if self.crashedTracksController is not None: self.crashedTracksController.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.crashedTracksController is not None: self.crashedTracksController.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.damageState 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.__requestModelsRefresh() elif not vehicle.isCrewActive: self.__onCrewKilled() return 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 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, componentIdx, stickerID, segStart, segEnd): self.vehicleStickers.addDamageSticker(code, componentIdx, stickerID, segStart, segEnd, self.collisions) def receiveShotImpulse(self, direction, impulse): if BattleReplay.isPlaying( ) and BattleReplay.g_replayCtrl.isTimeWarpInProgress: return else: if not VehicleDamageState.isDamagedModel( self.damageState.modelState): self.swingingAnimator.receiveShotImpulse(direction, impulse) if self.crashedTracksController is not None: self.crashedTracksController.receiveShotImpulse( direction, impulse) return def recoil(self): self.__initiateRecoil(TankNodeNames.GUN_INCLINATION, 'HP_gunFire', self.gunRecoil) def multiGunRecoil(self, indexes): if self.gunAnimators is None: return else: for index in indexes: typeDescr = self.typeDescriptor gunNodeName = typeDescr.turret.multiGun[index].node gunFireNodeName = typeDescr.turret.multiGun[index].gunFire gunAnimator = self.gunAnimators[index] self.__initiateRecoil(gunNodeName, gunFireNodeName, gunAnimator) return def addCrashedTrack(self, isLeft): if not self._vehicle.isAlive(): return else: if self.crashedTracksController is not None: self.crashedTracksController.addTrack( isLeft, self.isLeftSideFlying if isLeft else self.isRightSideFlying) self.onChassisDestroySound(isLeft, True) return def delCrashedTrack(self, isLeft): if self.crashedTracksController is not None: self.crashedTracksController.delTrack(isLeft) self.onChassisDestroySound(isLeft, False) return def onChassisDestroySound(self, isLeft, destroy, wheelsIdx=-1): if not self._vehicle.isEnteringWorld and self.engineAudition: if wheelsIdx == -1: if isLeft: position = Math.Matrix( self.compoundModel.node( TankNodeNames.TRACK_LEFT_MID)).translation else: position = Math.Matrix( self.compoundModel.node( TankNodeNames.TRACK_RIGHT_MID)).translation materialType = 0 else: position = self.wheelsAnimator.getWheelWorldTransform( wheelsIdx).translation materialType = 0 if self.wheelsAnimator.isWheelDeflatable( wheelsIdx) else 1 vehicle = self.getVehicle() if not destroy and vehicle.isPlayerVehicle and any( (device.groupName == 'extraHealthReserve' for device in vehicle.getOptionalDevices() if device is not None)): SoundGroups.g_instance.playSound2D('cons_springs') self.engineAudition.onChassisDestroy(position, destroy, materialType) def turretDamaged(self): player = BigWorld.player() if player is None or self._vehicle is None or not self._vehicle.isPlayerVehicle: return 0 else: deviceStates = getattr(player, 'deviceStates', None) if deviceStates is not None: if deviceStates.get('turretRotator', None) is None: return 0 return 1 return 0 def maxTurretRotationSpeed(self): player = BigWorld.player() if player is None or self._vehicle is None or not self._vehicle.isPlayerVehicle: return 0 else: gunRotator = getattr(player, 'gunRotator', None) return gunRotator.maxturretRotationSpeed if gunRotator is not None else 0 def _destroySystems(self): super(CompoundAppearance, self)._destroySystems() self.highlighter.destroy() def _prepareOutfit(self, outfitCD): outfit = camouflages.prepareBattleOutfit(outfitCD, self.typeDescriptor, self.id) return outfit def __initiateRecoil(self, gunNodeName, gunFireNodeName, gunAnimator): gunNode = self.compoundModel.node(gunNodeName) impulseDir = Math.Matrix(gunNode).applyVector(Math.Vector3(0, 0, -1)) impulseValue = self.typeDescriptor.gun.impulse self.receiveShotImpulse(impulseDir, impulseValue) gunAnimator.recoil() node = self.compoundModel.node(gunFireNodeName) gunPos = Math.Matrix(node).translation BigWorld.player().inputHandler.onVehicleShaken( self._vehicle, gunPos, impulseDir, self.typeDescriptor.shot.shell.caliber, ShakeReason.OWN_SHOT_DELAYED) def __applyVehicleOutfit(self): camouflages.updateFashions(self) def getBounds(self, partIdx): return self.collisions.getBoundingBox( DamageFromShotDecoder.convertComponentIndex(partIdx) ) if self.collisions is not None else (Math.Vector3(0.0, 0.0, 0.0), Math.Vector3(0.0, 0.0, 0.0), 0) def __requestModelsRefresh(self): self._onRequestModelsRefresh() modelsSetParams = self.modelsSetParams assembler = model_assembler.prepareCompoundAssembler( self.typeDescriptor, modelsSetParams, self._vehicle.spaceID, self._vehicle.isTurretDetached) BigWorld.loadResourceListBG((assembler, ), makeCallbackWeak(self.__onModelsRefresh, modelsSetParams.state), loadingPriority(self._vehicle.id)) def __onModelsRefresh(self, modelState, resourceList): if BattleReplay.isFinished(): return elif self._vehicle is None: return else: prevTurretYaw = Math.Matrix(self.turretMatrix).yaw prevGunPitch = Math.Matrix(self.gunMatrix).pitch vehicle = self._vehicle newCompoundModel = resourceList[self.typeDescriptor.name] isRightSideFlying = self.isRightSideFlying isLeftSideFlying = self.isLeftSideFlying self.deactivate(False) self.shadowManager.reattachCompoundModel(vehicle, self.compoundModel, newCompoundModel) self._compoundModel = newCompoundModel self._isTurretDetached = vehicle.isTurretDetached self.__prepareSystemsForDamagedVehicle(vehicle, self.isTurretDetached) self.__processPostmortemComponents() if isRightSideFlying: self.fashion.changeTrackVisibility(False, False) if isLeftSideFlying: self.fashion.changeTrackVisibility(True, False) self._setupModels() self.setVehicle(vehicle) self.activate() self.__reattachComponents(self.compoundModel) self.filter.syncGunAngles(prevTurretYaw, prevGunPitch) model_assembler.setupTurretRotations(self) return def __reattachComponents(self, model): self.boundEffects.reattachTo(model) if self.engineAudition is not None: self.engineAudition.setWeaponEnergy(self._weaponEnergy) self.engineAudition.attachToModel(model) return def __onCrewKilled(self): self.__destroyEngineAudition() if self.customEffectManager is not None: self.customEffectManager = None self.siegeEffects = 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.damageState.effect not in ( 'submersionDeath', ): self._stopEffects() extra = self._vehicle.typeDescriptor.extrasDict['fire'] if extra.isRunningFor(self._vehicle): extra.checkUnderwater(self._vehicle, isUnderWater) def updateTracksScroll(self, leftScroll, rightScroll): if self.trackScrollController is not None: self.trackScrollController.setExternal(leftScroll, rightScroll) return def __onPeriodicTimerEngine(self): return None if self.detailedEngineState is None or self.engineAudition is None else _PERIODIC_TIME_ENGINE def _periodicUpdate(self): super(CompoundAppearance, self)._periodicUpdate() if self._vehicle is None: return else: if self.peripheralsController is not None: self.peripheralsController.update(self._vehicle, self.crashedTracksController) if not self._vehicle.isAlive(): return self.__updateTransmissionScroll() return def __onPeriodicTimerDirt(self): if self.fashion is None: return else: dt = 1.0 distanceFromPlayer = self.lodCalculator.lodDistance if 0.0 <= distanceFromPlayer < _PERIODIC_TIME_DIRT[1][1]: time = BigWorld.time() simDt = time - self.__dirtUpdateTime if simDt > 0.0: if self.dirtComponent: roll = Math.Matrix(self.compoundModel.matrix).roll hasContact = 0 waterHeight = self.waterHeight if math.fabs(roll) > math.radians(120.0): hasContact = 2 if self.waterSensor.isInWater: waterHeight = 1.0 elif self.trackScrollController is not None: hasContact = 0 if self.trackScrollController.hasContact( ) else 1 self.dirtComponent.update( self.filter.averageSpeed, waterHeight, self.waterSensor.waterHeightWorld, self.terrainMatKind[2], hasContact, simDt) self.__dirtUpdateTime = time if distanceFromPlayer <= _PERIODIC_TIME_DIRT[1][ 0] or self._vehicle.isPlayerVehicle: dt = _PERIODIC_TIME_DIRT[0][0] else: dt = _PERIODIC_TIME_DIRT[0][ 0] + _DIRT_ALPHA * distanceFromPlayer return dt 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): insigniaRank = self._vehicle.publicInfo['marksOnGun'] vehicleStickers = VehicleStickers(self.typeDescriptor, insigniaRank, self.outfit) clanID = BigWorld.player().arena.vehicles[self._vehicle.id]['clanDBID'] vehicleStickers.setClanID(clanID) return vehicleStickers def __createTerrainCircle(self): if self.__terrainCircle is not None: return else: self.__terrainCircle = TerrainCircleComponent() return def __attachTerrainCircle(self): self.__terrainCircle.attach(self._vehicle.id) def computeFullVehicleLength(self): vehicleLength = 0.0 if self.compoundModel is not None: hullBB = Math.Matrix( self.compoundModel.getBoundsForPart(TankPartIndexes.HULL)) vehicleLength = hullBB.applyVector(Math.Vector3(0.0, 0.0, 1.0)).length return vehicleLength def setupGunMatrixTargets(self, target): self.turretMatrix.target = target.turretMatrix self.gunMatrix.target = target.gunMatrix def onFriction(self, otherID, frictionPoint, state): if self.frictionAudition is not None: self.frictionAudition.processFriction(otherID, frictionPoint, state) return def onSiegeStateChanged(self, newState, timeToNextMode): if self.engineAudition is not None: self.engineAudition.onSiegeStateChanged(newState) if self.hullAimingController is not None: self.hullAimingController.onSiegeStateChanged(newState) if self.suspensionSound is not None: self.suspensionSound.vehicleState = newState if self.siegeEffects is not None: self.siegeEffects.onSiegeStateChanged(newState, timeToNextMode) enabled = newState == VEHICLE_SIEGE_STATE.ENABLED or newState == VEHICLE_SIEGE_STATE.SWITCHING_ON if self.suspension is not None: self.suspension.setLiftMode(enabled) if self.leveredSuspension is not None: self.leveredSuspension.setLiftMode(enabled) if self.vehicleTraces is not None: self.vehicleTraces.setLiftMode(enabled) 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) if self.tracks is not None: if cameraName == 'sniper': self.tracks.sniperMode(True) else: self.tracks.sniperMode(False) return def __onEngineStateGearUp(self): if self.customEffectManager is not None: self.customEffectManager.onGearUp() if self.engineAudition is not None: self.engineAudition.onEngineGearUp() return def __updateTransmissionScroll(self): self._commonSlip = 0.0 self._commonScroll = 0.0 worldMatrix = Math.Matrix(self.compoundModel.matrix) zAxis = worldMatrix.applyToAxis(2) vehicleSpeed = zAxis.dot(self.filter.velocity) if self.wheelsScroll is not None: wheelsSpeed = self.wheelsAnimator.getWheelsSpeed() wheelCount = len(wheelsSpeed) skippedWheelsCount = 0 for wheelIndex in xrange(0, wheelCount): flying = self.wheelsAnimator.wheelIsFlying(wheelIndex) if not flying: self._commonScroll += wheelsSpeed[wheelIndex] self._commonSlip += wheelsSpeed[wheelIndex] - vehicleSpeed skippedWheelsCount += 1 activeWheelCount = max(wheelCount - skippedWheelsCount, 1) self._commonSlip /= activeWheelCount self._commonScroll /= activeWheelCount elif self.trackScrollController is not None: self._commonScroll = max(self.trackScrollController.leftScroll(), self.trackScrollController.rightScroll()) self._commonSlip = max(self.trackScrollController.leftSlip(), self.trackScrollController.rightSlip()) return def addCameraCollider(self): collider = self.collisions if collider is not None: colliderData = (collider.getColliderID(), (TankPartNames.getIdx(TankPartNames.HULL), TankPartNames.getIdx(TankPartNames.TURRET), TankPartNames.getIdx(TankPartNames.GUN))) BigWorld.appendCameraCollider(colliderData) return def removeCameraCollider(self): collider = self.collisions if collider is not None: BigWorld.removeCameraCollider(collider.getColliderID()) return def onEngineDamageRisk(self, risk): if self.engineAudition is not None: self.engineAudition.onEngineDamageRisk(risk) return def getWheelsSteeringMax(self): if self.wheelsSteering is not None and len(self.wheelsSteering) >= 2: wheelSteeringMax = self.wheelsSteering[0] if math.fabs(self.wheelsSteering[1]) > math.fabs(wheelSteeringMax): wheelSteeringMax = self.wheelsSteering[1] return -wheelSteeringMax else: return 0