class DetachedTurret(BigWorld.Entity, ComponentSystem): allTurrets = list() def __init__(self): ComponentSystem.__init__(self) 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): assembler = BigWorld.CompoundAssembler(self.__vehDescr.name, self.spaceID) turretModel = self.__vehDescr.turret.models.exploded gunModel = self.__vehDescr.gun.models.exploded assembler.addRootPart(turretModel, TankPartNames.TURRET) assembler.emplacePart(gunModel, TankNodeNames.GUN_JOINT, TankPartNames.GUN) return assembler def prerequisites(self): prereqs = [self.__prepareModelAssembler()] prereqs += self.__vehDescr.prerequisites() return prereqs def onEnterWorld(self, prereqs): self.model = prereqs[self.__vehDescr.name] self.model.matrix = self.matrix 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) for desc in self.__componentsDesc: desc.hitTester.loadBspModel() from helpers.CallbackDelayer import CallbackDelayer self.__isBeingPulledCallback = CallbackDelayer() self.__isBeingPulledCallback.delayCallback(self.__checkIsBeingPulled(), self.__checkIsBeingPulled) DetachedTurret.allTurrets.append(self) ProjectileAwareEntities.addEntity(self) BigWorld.callback(0.0, self.__createAndAttachStickers) return def __createAndAttachStickers(self): if self.__vehicleStickers is not None: return else: from VehicleStickers import VehicleStickers vehicle = BigWorld.entity(self.vehicleID) if vehicle is not None: 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) return def onLeaveWorld(self): ComponentSystem.destroy(self) DetachedTurret.allTurrets.remove(self) ProjectileAwareEntities.removeEntity(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) if distToWater != -1: 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): maxHitEffectCode, decodedPoints, _ = DamageFromShotDecoder.decodeHitPoints( points, self.__vehDescr) for shotPoint in decodedPoints: if shotPoint.componentName == TankPartNames.TURRET or shotPoint.componentName == TankPartNames.GUN: self.__hitEffects.showHit(shotPoint, effectsIndex, shotPoint.componentName) else: LOG_ERROR( "Detached turret got hit into %s component, but it's impossible" % shotPoint.componentName) def collideSegment(self, startPoint, endPoint, skipGun=False): res = None filterMethod = getattr(self.filter, 'segmentMayHitEntity', lambda: True) if not filterMethod(startPoint, endPoint, 0): return res else: matricesToCheck = [Matrix(self.model.matrix)] if not skipGun: matricesToCheck.append( Matrix(self.model.node(TankPartNames.GUN))) for matrix, desc in zip(matricesToCheck, self.__componentsDesc): toModel = matrix toModel.invert() collisions = desc.hitTester.localHitTest( toModel.applyPoint(startPoint), toModel.applyPoint(endPoint)) if collisions is None: continue for dist, _, hitAngleCos, matKind in collisions: if res is None or res.dist >= dist: matInfo = desc.materials.get(matKind) res = SegmentCollisionResult( dist, hitAngleCos, matInfo.armor if matInfo is not None else 0) return res 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 self.__createAndAttachStickers() 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 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