예제 #1
0
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
예제 #2
0
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