def update(self): global printedVehicle self.vehicle = BigWorld.entity(self.vehicleID) if self.vehicle is not None: if self.vehicle.health > 0 and self.vehicle.isAlive(): self.isAlive = True if self.isAlive is False or self.vehicle is None or (self.vehicle is not None and self.vehicle.health <= 0): print('[predictAim] enemy died or does not exists') self.hideVisible() return if not hasattr(BigWorld.player(), 'vehicleTypeDescriptor') or not hasattr(BigWorld.player(), 'gunRotator') or (hasattr(self.vehicle,"health") and self.vehicle.health <= 0): print('[predictAim] player has no vehicleTypeDescriptor or gunRotator OR enemy is has no health or health is lower/same as zero') self.hideVisible() return if self.modelDot is not None and self.modelDot._StaticObjectMarker3D__model: playerVehicleID = BigWorld.player().playerVehicleID if playerVehicleID: playerVehicle = BigWorld.entity(playerVehicleID) playerPosition = playerVehicle.model.node("hull").position self.vehicle = BigWorld.entity(self.vehicleID) shotSpeed = BigWorld.player().vehicleTypeDescriptor.shot.speed distance = playerPosition.flatDistTo(self.vehicle.model.node("hull").position) traveltime = distance / shotSpeed enemyCurrentSpeed = self.vehicle.speedInfo.value if self.lastSpeedValue is None or self.lastSpeedValue is enemyCurrentSpeed: self.lastSpeedValue = enemyCurrentSpeed enemyCurrentSpeed = (enemyCurrentSpeed + self.lastSpeedValue) / 2 self.lastSpeedValue = enemyCurrentSpeed centerFront = self.vehicle.model.node("hull").position cMin , cMax , _ = self.vehicle.getBounds(TankPartIndexes.CHASSIS) _ , hMax , _ = self.vehicle.getBounds(TankPartIndexes.HULL) hMax.y += cMax.y _ , tMax , _ =self.vehicle.getBounds(TankPartIndexes.TURRET) tMax.y += hMax.y cMax.y = tMax.y matrix = Matrix(self.vehicle.matrix) FRONT_RIGTH_BOTTOM = matrix.applyVector(Vector3(cMax.x , cMin.y , cMax.z )) + self.vehicle.position FRONT_LEFT_BOTTOM = matrix.applyVector(Vector3(cMin.x , cMin.y , cMax.z )) + self.vehicle.position centerFront = (FRONT_RIGTH_BOTTOM + FRONT_LEFT_BOTTOM)/2 #print("[predictAim]: center Front pos: %s" % centerFront) #print("[predictAim]: hull: %s" % self.vehicle.model.node("hull").position) #print("[predictAim]: center Back pos: %s" % centerBack) travel_distance_0 = enemyCurrentSpeed[0] * traveltime #travel_distance_2 = enemyCurrentSpeed[2] * traveltime v = centerFront - self.vehicle.model.node("hull").position v3 = Vector3(v) #v3.normalise() predPos_test = self.vehicle.model.node("hull").position + (v3*travel_distance_0) tmp_veh = BigWorld.entity(self.vehicleID) predPos_test[1] = tmp_veh.model.node("hull").position[1] self.modelDot._StaticObjectMarker3D__model.position = predPos_test self.modelDot._StaticObjectMarker3D__model.visible = True
def __update(self, dx, dy, dz, rotateMode = True, zoomMode = True, isCallback = False): prevPos = self.__inputInertia.calcWorldPos(self.__aimingSystem.matrix) distChanged = False if zoomMode and dz != 0: prevDist = self.__aimingSystem.distanceFromFocus distDelta = dz * float(self.__curScrollSense) distMinMax = self.__cfg['distRange'] newDist = mathUtils.clamp(distMinMax.min, distMinMax.max, prevDist - distDelta) if abs(newDist - prevDist) > 0.001: self.__aimingSystem.distanceFromFocus = newDist self.__userCfg['startDist'] = newDist self.__inputInertia.glideFov(self.__calcRelativeDist()) self.__aimingSystem.aimMatrix = self.__calcAimMatrix() distChanged = True changeControlMode = prevDist == newDist and mathUtils.almostZero(newDist - distMinMax.min) if changeControlMode and self.__onChangeControlMode is not None: self.__onChangeControlMode() return if rotateMode: self.__updateAngles(dx, dy) if ENABLE_INPUT_ROTATION_INERTIA and not distChanged: self.__aimingSystem.update(0.0) if ENABLE_INPUT_ROTATION_INERTIA or distChanged: worldDeltaPos = prevPos - self.__aimingSystem.matrix.translation matInv = Matrix(self.__aimingSystem.matrix) matInv.invert() self.__inputInertia.glide(matInv.applyVector(worldDeltaPos)) return
def __update(self, dx, dy, dz, rotateMode = True, zoomMode = True, isCallback = False): prevPos = self.__inputInertia.calcWorldPos(self.__aimingSystem.matrix) distChanged = False if zoomMode and dz != 0: prevDist = self.__aimingSystem.distanceFromFocus distDelta = dz * float(self.__curScrollSense) distMinMax = self.__cfg['distRange'] newDist = mathUtils.clamp(distMinMax.min, distMinMax.max, prevDist - distDelta) if abs(newDist - prevDist) > 0.001: self.__aimingSystem.distanceFromFocus = newDist self.__userCfg['startDist'] = newDist self.__inputInertia.glideFov(self.__calcRelativeDist()) self.__aimingSystem.aimMatrix = self.__calcAimMatrix() distChanged = True changeControlMode = prevDist == newDist and mathUtils.almostZero(newDist - distMinMax.min) if changeControlMode and self.__onChangeControlMode is not None: self.__onChangeControlMode() return if rotateMode: self.__updateAngles(dx, dy) if ENABLE_INPUT_ROTATION_INERTIA and not distChanged: self.__aimingSystem.update(0.0) if ENABLE_INPUT_ROTATION_INERTIA or distChanged: worldDeltaPos = prevPos - self.__aimingSystem.matrix.translation matInv = Matrix(self.__aimingSystem.matrix) matInv.invert() self.__inputInertia.glide(matInv.applyVector(worldDeltaPos))
def __calcCurOscillatorAcceleration(self, deltaTime): vehicle = BigWorld.player().vehicle if vehicle is None or not vehicle.isAlive(): return Vector3(0, 0, 0) else: curVelocity = vehicle.filter.velocity relativeSpeed = curVelocity.length / vehicle.typeDescriptor.physics[ 'speedLimits'][0] if relativeSpeed >= SniperCamera._MIN_REL_SPEED_ACC_SMOOTHING: self.__accelerationSmoother.maxAllowedAcceleration = self.__dynamicCfg[ 'accelerationThreshold'] else: self.__accelerationSmoother.maxAllowedAcceleration = self.__dynamicCfg[ 'accelerationMax'] acceleration = self.__accelerationSmoother.update( vehicle, deltaTime) camMat = Matrix(self.__cam.matrix) acceleration = camMat.applyVector(-acceleration) accelSensitivity = self.__dynamicCfg['accelerationSensitivity'] acceleration.x *= accelSensitivity.x acceleration.y *= accelSensitivity.y acceleration.z *= accelSensitivity.z oscillatorAcceleration = Vector3(0, -acceleration.y + acceleration.z, -acceleration.x) return oscillatorAcceleration
def update(self, vehicle, deltaTime): try: curVelocity = vehicle.filter.velocity acceleration = vehicle.filter.acceleration acceleration = self.__accelerationFilter.add(acceleration) movementFlags = vehicle.engineMode[1] moveMask = 3 self.__hasChangedDirection = movementFlags & moveMask ^ self.__prevMovementFlags & moveMask or curVelocity.dot( self.__prevVelocity) <= 0.01 self.__prevMovementFlags = movementFlags self.__prevVelocity = curVelocity self.__timeLapsedSinceDirChange += deltaTime if self.__hasChangedDirection: self.__timeLapsedSinceDirChange = 0.0 elif self.__timeLapsedSinceDirChange > self.__maxAccelerationDuration: invVehMat = Matrix(vehicle.matrix) invVehMat.invert() accelerationRelativeToVehicle = invVehMat.applyVector( acceleration) accelerationRelativeToVehicle.x = 0.0 accelerationRelativeToVehicle.z = 0.0 acceleration = Matrix( vehicle.matrix).applyVector(accelerationRelativeToVehicle) self.__acceleration = acceleration return acceleration except: return Math.Vector3(0.0, 0.0, 0.0)
def applyImpulse(self, position, impulse, reason = ImpulseReason.ME_HIT): adjustedImpulse, noiseMagnitude = self.__dynamicCfg.adjustImpulse(impulse, reason) camMatrix = Matrix(self.__cam.matrix) impulseLocal = camMatrix.applyVector(adjustedImpulse) impulseAsYPR = Vector3(impulseLocal.x, -impulseLocal.y + impulseLocal.z, 0) rollPart = self.__dynamicCfg['impulsePartToRoll'] impulseAsYPR.z = -rollPart * impulseAsYPR.x impulseAsYPR.x *= 1 - rollPart self.__impulseOscillator.applyImpulse(impulseAsYPR) self.__applyNoiseImpulse(noiseMagnitude)
def applyImpulse(self, position, impulse, reason=ImpulseReason.ME_HIT): adjustedImpulse, noiseMagnitude = self.__dynamicCfg.adjustImpulse(impulse, reason) camMatrix = Matrix(self.__cam.matrix) impulseLocal = camMatrix.applyVector(adjustedImpulse) impulseAsYPR = Vector3(impulseLocal.x, -impulseLocal.y + impulseLocal.z, 0) rollPart = self.__dynamicCfg['impulsePartToRoll'] impulseAsYPR.z = -rollPart * impulseAsYPR.x impulseAsYPR.x *= 1 - rollPart self.__impulseOscillator.applyImpulse(impulseAsYPR) self.__applyNoiseImpulse(noiseMagnitude)
def __calcCurOscillatorAcceleration(self, deltaTime): vehicle = BigWorld.player().vehicle if vehicle is None: return Vector3(0, 0, 0) curVelocity = vehicle.filter.velocity relativeSpeed = curVelocity.length / vehicle.typeDescriptor.physics['speedLimits'][0] if relativeSpeed >= SniperCamera._MIN_REL_SPEED_ACC_SMOOTHING: self.__accelerationSmoother.maxAllowedAcceleration = self.__dynamicCfg['accelerationThreshold'] else: self.__accelerationSmoother.maxAllowedAcceleration = self.__dynamicCfg['accelerationMax'] acceleration = self.__accelerationSmoother.update(vehicle, deltaTime) camMat = Matrix(self.__cam.matrix) acceleration = camMat.applyVector(-acceleration) accelSensitivity = self.__dynamicCfg['accelerationSensitivity'] acceleration.x *= accelSensitivity.x acceleration.y *= accelSensitivity.y acceleration.z *= accelSensitivity.z oscillatorAcceleration = Vector3(0, -acceleration.y + acceleration.z, -acceleration.x) return oscillatorAcceleration
def checkTurretDetachment(self, worldPos): if self.__vehicle is None: return if self.__vehicle.isTurretDetached and not self.__placement == _VehicleBounder.SELECT_DETACHED_TURRET: turretFound = None for turret in DetachedTurret.allTurrets: if turret.vehicleID == self.__vehicle.id and turret.model.visible: turretFound = turret break if turretFound is None: return turretToGoalShift = worldPos - turretFound.position toTurretMat = Matrix(turretFound.matrix) toTurretMat.invert() turretToGoalShift = toTurretMat.applyVector(turretToGoalShift) self.matrix = turretFound.matrix self.__lookAtProvider = None self.__placement = _VehicleBounder.SELECT_DETACHED_TURRET return turretToGoalShift
def update(self, vehicle, deltaTime): curVelocity = vehicle.filter.velocity acceleration = vehicle.filter.acceleration acceleration = self.__accelerationFilter.add(acceleration) movementFlags = vehicle.engineMode[1] moveMask = 3 self.__hasChangedDirection = movementFlags & moveMask ^ self.__prevMovementFlags & moveMask or curVelocity.dot(self.__prevVelocity) <= 0.01 self.__prevMovementFlags = movementFlags self.__prevVelocity = curVelocity self.__timeLapsedSinceDirChange += deltaTime if self.__hasChangedDirection: self.__timeLapsedSinceDirChange = 0.0 elif self.__timeLapsedSinceDirChange > self.__maxAccelerationDuration: invVehMat = Matrix(vehicle.matrix) invVehMat.invert() accelerationRelativeToVehicle = invVehMat.applyVector(acceleration) accelerationRelativeToVehicle.x = 0.0 accelerationRelativeToVehicle.z = 0.0 acceleration = Matrix(vehicle.matrix).applyVector(accelerationRelativeToVehicle) self.__acceleration = acceleration return acceleration
def checkTurretDetachment(self, worldPos): if self.__vehicle is None: return elif self.__vehicle.isTurretDetached and not self.__placement == _VehicleBounder.SELECT_DETACHED_TURRET: turretFound = None for turret in DetachedTurret.allTurrets: if turret.vehicleID == self.__vehicle.id and turret.model.visible: turretFound = turret break if turretFound is None: return turretToGoalShift = worldPos - turretFound.position toTurretMat = Matrix(turretFound.matrix) toTurretMat.invert() turretToGoalShift = toTurretMat.applyVector(turretToGoalShift) self.matrix = turretFound.matrix self.__lookAtProvider = None self.__placement = _VehicleBounder.SELECT_DETACHED_TURRET return turretToGoalShift else: return
class ArtyCamera(ICamera, CallbackDelayer): _DYNAMIC_ENABLED = True @staticmethod def enableDynamicCamera(enable): ArtyCamera._DYNAMIC_ENABLED = enable @staticmethod def isCameraDynamic(): return ArtyCamera._DYNAMIC_ENABLED camera = property(lambda self: self.__cam) aimingSystem = property(lambda self: self.__aimingSystem) settingsCore = dependency.descriptor(ISettingsCore) __aimOffset = aih_global_binding.bindRW( aih_global_binding.BINDING_ID.AIM_OFFSET) def __init__(self, dataSec): CallbackDelayer.__init__(self) self.__positionOscillator = None self.__positionNoiseOscillator = None self.__dynamicCfg = CameraDynamicConfig() self.__readCfg(dataSec) self.__cam = BigWorld.CursorCamera() self.__curSense = self.__cfg['sensitivity'] self.__onChangeControlMode = None self.__camDist = 0.0 self.__desiredCamDist = 0.0 self.__aimingSystem = None self.__prevTime = 0.0 self.__dxdydz = Vector3(0.0, 0.0, 0.0) self.__autoUpdatePosition = False self.__needReset = 0 self.__sourceMatrix = None self.__targetMatrix = None self.__rotation = 0.0 self.__positionHysteresis = None self.__timeHysteresis = None return def create(self, onChangeControlMode=None): self.__onChangeControlMode = onChangeControlMode aimingSystemClass = ArtyAimingSystemRemote if BigWorld.player( ).isObserver() else ArtyAimingSystem self.__aimingSystem = aimingSystemClass() self.__camDist = self.__cfg['camDist'] self.__desiredCamDist = self.__camDist self.__positionHysteresis = PositionHysteresis( self.__cfg['hPositionThresholdSq']) self.__timeHysteresis = TimeHysteresis(self.__cfg['hTimeThreshold']) self.__cam.pivotMaxDist = 0.0 self.__cam.maxDistHalfLife = 0.01 self.__cam.movementHalfLife = 0.0 self.__cam.turningHalfLife = -1 self.__cam.pivotPosition = Vector3(0.0, 0.0, 0.0) self.__sourceMatrix = Matrix() self.__targetMatrix = Matrix() self.__rotation = 0.0 def destroy(self): CallbackDelayer.destroy(self) self.disable() self.__onChangeControlMode = None self.__cam = None if self.__aimingSystem is not None: self.__aimingSystem.destroy() self.__aimingSystem = None return def enable(self, targetPos, saveDist): self.__prevTime = 0.0 self.__aimingSystem.enable(targetPos) self.__positionHysteresis.update(Vector3(0.0, 0.0, 0.0)) self.__timeHysteresis.update(BigWorld.timeExact()) camTarget = MatrixProduct() self.__cam.target = camTarget self.__cam.source = self.__sourceMatrix self.__cam.wg_applyParams() BigWorld.camera(self.__cam) BigWorld.player().positionControl.moveTo(self.__aimingSystem.hitPoint) BigWorld.player().positionControl.followCamera(False) self.__rotation = 0.0 self.__cameraUpdate() self.delayCallback(0.0, self.__cameraUpdate) self.__needReset = 1 def disable(self): if self.__aimingSystem is not None: self.__aimingSystem.disable() self.stopCallback(self.__cameraUpdate) BigWorld.camera(None) self.__positionOscillator.reset() return def teleport(self, pos): self.__aimingSystem.updateTargetPos(pos) self.update(0.0, 0.0, 0.0) def getConfigValue(self, name): return self.__cfg.get(name) def getUserConfigValue(self, name): return self.__userCfg.get(name) def setUserConfigValue(self, name, value): if name not in self.__userCfg: return self.__userCfg[name] = value if name not in ('keySensitivity', 'sensitivity', 'scrollSensitivity'): self.__cfg[name] = self.__userCfg[name] else: self.__cfg[name] = self.__baseCfg[name] * self.__userCfg[name] def update(self, dx, dy, dz, updateByKeyboard=False): self.__curSense = self.__cfg[ 'keySensitivity'] if updateByKeyboard else self.__cfg['sensitivity'] self.__autoUpdatePosition = updateByKeyboard self.__dxdydz = Vector3(dx if not self.__cfg['horzInvert'] else -dx, dy if not self.__cfg['vertInvert'] else -dy, dz) def applyImpulse(self, position, impulse, reason=ImpulseReason.ME_HIT): adjustedImpulse, noiseMagnitude = self.__dynamicCfg.adjustImpulse( impulse, reason) impulseFlatDir = Vector3(adjustedImpulse.x, 0, adjustedImpulse.z) impulseFlatDir.normalise() impulseLocal = self.__sourceMatrix.applyVector( impulseFlatDir * (-1 * adjustedImpulse.length)) self.__positionOscillator.applyImpulse(impulseLocal) self.__applyNoiseImpulse(noiseMagnitude) def applyDistantImpulse(self, position, impulseValue, reason=ImpulseReason.ME_HIT): if reason != ImpulseReason.SPLASH and reason != ImpulseReason.PROJECTILE_HIT: return impulse = BigWorld.player().getOwnVehiclePosition() - position distance = impulse.length if distance <= 1.0: distance = 1.0 impulse.normalise() if reason == ImpulseReason.PROJECTILE_HIT: if not cameras.isPointOnScreen(position): return distance = 1.0 impulse *= impulseValue / distance self.applyImpulse(position, impulse, reason) def writeUserPreferences(self): ds = Settings.g_instance.userPrefs if not ds.has_key(Settings.KEY_CONTROL_MODE): ds.write(Settings.KEY_CONTROL_MODE, '') ucfg = self.__userCfg ds = ds[Settings.KEY_CONTROL_MODE] ds.writeBool('artyMode/camera/horzInvert', ucfg['horzInvert']) ds.writeBool('artyMode/camera/vertInvert', ucfg['vertInvert']) ds.writeFloat('artyMode/camera/keySensitivity', ucfg['keySensitivity']) ds.writeFloat('artyMode/camera/sensitivity', ucfg['sensitivity']) ds.writeFloat('artyMode/camera/scrollSensitivity', ucfg['scrollSensitivity']) ds.writeFloat('artyMode/camera/camDist', self.__cfg['camDist']) def __applyNoiseImpulse(self, noiseMagnitude): noiseImpulse = mathUtils.RandomVectors.random3Flat(noiseMagnitude) self.__positionNoiseOscillator.applyImpulse(noiseImpulse) def __calculateAimOffset(self, aimWorldPos): replayCtrl = BattleReplay.g_replayCtrl if replayCtrl.isPlaying and replayCtrl.isControllingCamera: aimOffset = replayCtrl.getAimClipPosition() else: aimOffset = cameras.projectPoint(aimWorldPos) aimOffset = Vector2(mathUtils.clamp(-0.95, 0.95, aimOffset.x), mathUtils.clamp(-0.95, 0.95, aimOffset.y)) if replayCtrl.isRecording: replayCtrl.setAimClipPosition(aimOffset) return aimOffset def __handleMovement(self): replayCtrl = BattleReplay.g_replayCtrl if replayCtrl.isPlaying: if self.__needReset != 0: if self.__needReset > 1: from helpers import isPlayerAvatar player = BigWorld.player() if isPlayerAvatar(): if player.inputHandler.ctrl is not None: player.inputHandler.ctrl.resetGunMarkers() self.__needReset = 0 else: self.__needReset += 1 if replayCtrl.isControllingCamera: self.__aimingSystem.updateTargetPos( replayCtrl.getGunRotatorTargetPoint()) else: self.__aimingSystem.handleMovement( self.__dxdydz.x * self.__curSense, -self.__dxdydz.y * self.__curSense) if self.__dxdydz.x != 0 or self.__dxdydz.y != 0 or self.__dxdydz.z != 0: self.__needReset = 2 else: self.__aimingSystem.handleMovement( self.__dxdydz.x * self.__curSense, -self.__dxdydz.y * self.__curSense) return def __getCameraDirection(self): direction = Vector3() direction.setPitchYaw(self.__rotation, self.__aimingSystem.direction.yaw) direction.normalise() return direction def __getDesiredCameraDistance(self): distRange = self.__cfg['distRange'] self.__desiredCamDist -= self.__dxdydz.z * self.__curSense self.__desiredCamDist = mathUtils.clamp(distRange[0], distRange[1], self.__desiredCamDist) self.__desiredCamDist = self.__aimingSystem.overrideCamDist( self.__desiredCamDist) self.__cfg['camDist'] = self.__camDist return self.__desiredCamDist def __updateTrajectoryDrawer(self): shotDescr = BigWorld.player().getVehicleDescriptor().shot BigWorld.wg_trajectory_drawer().setParams( shotDescr.maxDistance, Vector3(0, -shotDescr.gravity, 0), self.__aimOffset) def __updateTime(self): curTime = BigWorld.timeExact() deltaTime = curTime - self.__prevTime self.__prevTime = curTime return deltaTime def __choosePitchLevel(self, aimPoint): useHighPitch = (aimPoint - self.__aimingSystem.hitPoint ).lengthSquared > self.__cfg['highPitchThresholdSq'] if useHighPitch: useHighPitch = self.__positionHysteresis.check( aimPoint) or self.__timeHysteresis.check(self.__prevTime) else: self.__positionHysteresis.update(aimPoint) self.__timeHysteresis.update(self.__prevTime) return useHighPitch def __getCollisionTestOrigin(self, aimPoint, direction): distRange = self.__cfg['distRange'] vehiclePosition = BigWorld.player().getVehicleAttached().position collisionTestOrigin = Vector3(vehiclePosition) if direction.x * direction.x > direction.z * direction.z and not mathUtils.almostZero( direction.x): collisionTestOrigin.y = direction.y / direction.x * ( vehiclePosition.x - aimPoint.x) + aimPoint.y elif not mathUtils.almostZero(direction.z): collisionTestOrigin.y = direction.y / direction.z * ( vehiclePosition.z - aimPoint.z) + aimPoint.y else: collisionTestOrigin = aimPoint - direction.scale( (distRange[1] - distRange[0]) / 2.0) LOG_WARNING( "Can't find point on direction ray. Using half point as collision test origin" ) return collisionTestOrigin def __resolveCollisions(self, aimPoint, distance, direction): distRange = self.__cfg['distRange'] collisionTestOrigin = self.__getCollisionTestOrigin( aimPoint, direction) sign = copysign( 1.0, distance * distance - (aimPoint - collisionTestOrigin).lengthSquared) srcPoint = collisionTestOrigin endPoint = aimPoint - direction.scale(distance + sign * distRange[0]) collision = collideDynamicAndStatic( srcPoint, endPoint, (BigWorld.player().playerVehicleID, )) if collision: collisionDistance = (aimPoint - collision[0]).length if sign * (collisionDistance - distance) < distRange[0]: distance = collisionDistance - sign * distRange[0] if mathUtils.almostZero(self.__rotation): srcPoint = aimPoint - direction.scale(distance) endPoint = aimPoint collision = collideDynamicAndStatic( srcPoint, endPoint, (BigWorld.player().playerVehicleID, )) if collision: self.__aimingSystem.aimPoint = collision[0] if collision[1]: self.__positionHysteresis.update(aimPoint) self.__timeHysteresis.update(self.__prevTime) return distance def __calculateIdealState(self, deltaTime): aimPoint = self.__aimingSystem.aimPoint direction = self.__aimingSystem.direction impactPitch = max(direction.pitch, self.__cfg['minimalPitch']) self.__rotation = max(self.__rotation, impactPitch) distRange = self.__cfg['distRange'] distanceCurSq = ( aimPoint - BigWorld.player().getVehicleAttached().position).lengthSquared distanceMinSq = distRange[0]**2.0 forcedPitch = impactPitch if distanceCurSq < distanceMinSq: forcedPitch = atan2(sqrt(distanceMinSq - distanceCurSq), sqrt(distanceCurSq)) angularShift = self.__cfg['angularSpeed'] * deltaTime angularShift = angularShift if self.__choosePitchLevel( aimPoint) else -angularShift minPitch = max(forcedPitch, impactPitch) maxPitch = max(forcedPitch, self.__cfg['maximalPitch']) self.__rotation = mathUtils.clamp(minPitch, maxPitch, self.__rotation + angularShift) desiredDistance = self.__getDesiredCameraDistance() cameraDirection = self.__getCameraDirection() desiredDistance = self.__resolveCollisions(aimPoint, desiredDistance, cameraDirection) desiredDistance = mathUtils.clamp(distRange[0], distRange[1], desiredDistance) translation = aimPoint - cameraDirection.scale(desiredDistance) rotation = Vector3(cameraDirection.yaw, -cameraDirection.pitch, 0.0) return (translation, rotation) def __interpolateStates(self, deltaTime, translation, rotation): lerpParam = mathUtils.clamp( 0.0, 1.0, deltaTime * self.__cfg['interpolationSpeed']) self.__sourceMatrix = slerp(self.__sourceMatrix, rotation, lerpParam) self.__targetMatrix.translation = mathUtils.lerp( self.__targetMatrix.translation, translation, lerpParam) return (self.__sourceMatrix, self.__targetMatrix) def __cameraUpdate(self): deltaTime = self.__updateTime() self.__handleMovement() aimPoint = Vector3(self.__aimingSystem.aimPoint) self.__aimOffset = self.__calculateAimOffset(aimPoint) self.__updateTrajectoryDrawer() translation, rotation = self.__calculateIdealState(deltaTime) self.__interpolateStates(deltaTime, translation, mathUtils.createRotationMatrix(rotation)) self.__camDist = aimPoint - self.__targetMatrix.translation self.__camDist = self.__camDist.length self.__cam.source = self.__sourceMatrix self.__cam.target.b = self.__targetMatrix self.__cam.pivotPosition = Vector3(0, 0, 0) BigWorld.player().positionControl.moveTo(aimPoint) self.__updateOscillator(deltaTime) self.__aimingSystem.update(deltaTime) if not self.__autoUpdatePosition: self.__dxdydz = Vector3(0, 0, 0) return 0.0 def __updateOscillator(self, deltaTime): if ArtyCamera.isCameraDynamic(): self.__positionOscillator.update(deltaTime) self.__positionNoiseOscillator.update(deltaTime) else: self.__positionOscillator.reset() self.__positionNoiseOscillator.reset() self.__cam.target.a = mathUtils.createTranslationMatrix( self.__positionOscillator.deviation + self.__positionNoiseOscillator.deviation) def __readCfg(self, dataSec): if not dataSec: LOG_WARNING( 'Invalid section <artyMode/camera> in avatar_input_handler.xml' ) self.__baseCfg = dict() bcfg = self.__baseCfg bcfg['keySensitivity'] = readFloat(dataSec, 'keySensitivity', 0.005, 10.0, 0.025) bcfg['sensitivity'] = readFloat(dataSec, 'sensitivity', 0.005, 10.0, 0.025) bcfg['scrollSensitivity'] = readFloat(dataSec, 'scrollSensitivity', 0.005, 10.0, 0.025) bcfg['angularSpeed'] = readFloat(dataSec, 'angularSpeed', pi / 720.0, pi / 0.5, pi / 360.0) bcfg['distRange'] = readVec2(dataSec, 'distRange', (1.0, 1.0), (10000.0, 10000.0), (2.0, 30.0)) bcfg['minimalPitch'] = readFloat(dataSec, 'minimalPitch', pi / 36.0, pi / 3.0, pi / 18.0) bcfg['maximalPitch'] = readFloat(dataSec, 'maximalPitch', pi / 6.0, pi / 3.0, pi / 3.5) bcfg['interpolationSpeed'] = readFloat(dataSec, 'interpolationSpeed', 0.0, 10.0, 5.0) bcfg['highPitchThreshold'] = readFloat(dataSec, 'highPitchThreshold', 0.1, 10.0, 3.0) bcfg['hTimeThreshold'] = readFloat(dataSec, 'hysteresis/timeThreshold', 0.0, 10.0, 0.5) bcfg['hPositionThreshold'] = readFloat(dataSec, 'hysteresis/positionThreshold', 0.0, 100.0, 7.0) ds = Settings.g_instance.userPrefs[Settings.KEY_CONTROL_MODE] if ds is not None: ds = ds['artyMode/camera'] self.__userCfg = dict() ucfg = self.__userCfg ucfg['horzInvert'] = self.settingsCore.getSetting('mouseHorzInvert') ucfg['vertInvert'] = self.settingsCore.getSetting('mouseVertInvert') ucfg['keySensitivity'] = readFloat(ds, 'keySensitivity', 0.0, 10.0, 1.0) ucfg['sensitivity'] = readFloat(ds, 'sensitivity', 0.0, 10.0, 1.0) ucfg['scrollSensitivity'] = readFloat(ds, 'scrollSensitivity', 0.0, 10.0, 1.0) ucfg['camDist'] = readFloat(ds, 'camDist', 0.0, 60.0, 0.0) self.__cfg = dict() cfg = self.__cfg cfg['keySensitivity'] = bcfg['keySensitivity'] cfg['sensitivity'] = bcfg['sensitivity'] cfg['scrollSensitivity'] = bcfg['scrollSensitivity'] cfg['distRange'] = bcfg['distRange'] cfg['angularSpeed'] = bcfg['angularSpeed'] cfg['minimalPitch'] = bcfg['minimalPitch'] cfg['maximalPitch'] = bcfg['maximalPitch'] cfg['interpolationSpeed'] = bcfg['interpolationSpeed'] cfg['highPitchThresholdSq'] = bcfg['highPitchThreshold'] * bcfg[ 'highPitchThreshold'] cfg['hTimeThreshold'] = bcfg['hTimeThreshold'] cfg['hPositionThresholdSq'] = bcfg['hPositionThreshold'] * bcfg[ 'hPositionThreshold'] cfg['keySensitivity'] *= ucfg['keySensitivity'] cfg['sensitivity'] *= ucfg['sensitivity'] cfg['scrollSensitivity'] *= ucfg['scrollSensitivity'] cfg['camDist'] = ucfg['camDist'] cfg['horzInvert'] = ucfg['horzInvert'] cfg['vertInvert'] = ucfg['vertInvert'] dynamicSection = dataSec['dynamics'] self.__dynamicCfg.readImpulsesConfig(dynamicSection) self.__positionOscillator = createOscillatorFromSection( dynamicSection['oscillator'], False) self.__positionNoiseOscillator = createOscillatorFromSection( dynamicSection['randomNoiseOscillatorFlat'], False) return
class ArtyCamera(CameraWithSettings, CallbackDelayer): _DYNAMIC_ENABLED = True @staticmethod def enableDynamicCamera(enable): ArtyCamera._DYNAMIC_ENABLED = enable @staticmethod def isCameraDynamic(): return ArtyCamera._DYNAMIC_ENABLED camera = property(lambda self: self.__cam) aimingSystem = property(lambda self: self.__aimingSystem) __aimOffset = aih_global_binding.bindRW( aih_global_binding.BINDING_ID.AIM_OFFSET) def __init__(self, dataSec): super(ArtyCamera, self).__init__() CallbackDelayer.__init__(self) self.isAimOffsetEnabled = True self.__positionOscillator = None self.__positionNoiseOscillator = None self.__switchers = CameraSwitcherCollection(cameraSwitchers=[ CameraSwitcher(switchType=SwitchTypes.FROM_TRANSITION_DIST_AS_MAX, switchToName=CTRL_MODE_NAME.STRATEGIC, switchToPos=0.0) ], isEnabled=True) self.__dynamicCfg = CameraDynamicConfig() self._readConfigs(dataSec) self.__cam = BigWorld.CursorCamera() self.__curSense = self._cfg['sensitivity'] self.__onChangeControlMode = None self.__camDist = 0.0 self.__desiredCamDist = 0.0 self.__aimingSystem = None self.__prevTime = 0.0 self.__prevAimPoint = Vector3() self.__dxdydz = Vector3(0.0, 0.0, 0.0) self.__autoUpdatePosition = False self.__needReset = 0 self.__sourceMatrix = None self.__targetMatrix = None self.__rotation = 0.0 self.__positionHysteresis = None self.__timeHysteresis = None self.__transitionEnabled = True self.__scrollSmoother = SPGScrollSmoother(0.3) self.__collisionDist = 0.0 self.__camViewPoint = Vector3() return @staticmethod def _getConfigsKey(): return ArtyCamera.__name__ def create(self, onChangeControlMode=None): super(ArtyCamera, self).create() self.__onChangeControlMode = onChangeControlMode aimingSystemClass = ArtyAimingSystemRemote if BigWorld.player( ).isObserver() else ArtyAimingSystem self.__aimingSystem = aimingSystemClass() self.__camDist = self._cfg['camDist'] self.__desiredCamDist = self.__camDist self.__positionHysteresis = PositionHysteresis( self._cfg['hPositionThresholdSq']) self.__timeHysteresis = TimeHysteresis(self._cfg['hTimeThreshold']) self.__cam.pivotMaxDist = 0.0 self.__cam.maxDistHalfLife = 0.01 self.__cam.movementHalfLife = 0.0 self.__cam.turningHalfLife = -1 self.__cam.pivotPosition = Vector3(0.0, 0.0, 0.0) self.__sourceMatrix = Matrix() self.__targetMatrix = Matrix() self.__rotation = 0.0 self.__enableSwitchers() self.__scrollSmoother.setTime(self._cfg['scrollSmoothingTime']) def destroy(self): self.disable() self.__onChangeControlMode = None self.__cam = None if self.__aimingSystem is not None: self.__aimingSystem.destroy() self.__aimingSystem = None CallbackDelayer.destroy(self) CameraWithSettings.destroy(self) return def enable(self, targetPos, saveDist, switchToPos=None, switchToPlace=None): BigWorld.wg_trajectory_drawer().setStrategicMode(False) self.__prevTime = 0.0 if switchToPlace == SwitchToPlaces.TO_TRANSITION_DIST: self.__camDist = math_utils.clamp(self._cfg['distRange'][0], self._cfg['distRange'][1], self._cfg['transitionDist']) elif switchToPlace == SwitchToPlaces.TO_RELATIVE_POS and switchToPos is not None: minDist, maxDist = self._cfg['distRange'] self.__camDist = (maxDist - minDist) * switchToPos + minDist elif switchToPlace == SwitchToPlaces.TO_NEAR_POS and switchToPos is not None: minDist, maxDist = self._cfg['distRange'] self.__camDist = math_utils.clamp(minDist, maxDist, switchToPos) elif self.settingsCore.getSetting(SPGAim.AUTO_CHANGE_AIM_MODE): self.__camDist = math_utils.clamp(self._cfg['distRange'][0], self._cfg['transitionDist'], self.__camDist) self.__desiredCamDist = self.__camDist self.__scrollSmoother.start(self.__desiredCamDist) self.__enableSwitchers() self.__aimingSystem.enable(targetPos) self.__positionHysteresis.update(Vector3(0.0, 0.0, 0.0)) self.__timeHysteresis.update(BigWorld.timeExact()) camTarget = MatrixProduct() self.__rotation = max(self.__aimingSystem.direction.pitch, self._cfg['minimalPitch']) cameraDirection = self.__getCameraDirection() self.__targetMatrix.translation = self.aimingSystem.aimPoint - cameraDirection.scale( self.__camDist) self.__cam.target = camTarget self.__cam.target.b = self.__targetMatrix self.__sourceMatrix = math_utils.createRotationMatrix( (cameraDirection.yaw, -cameraDirection.pitch, 0.0)) self.__cam.source = self.__sourceMatrix self.__cam.forceUpdate() BigWorld.camera(self.__cam) BigWorld.player().positionControl.moveTo(self.__aimingSystem.hitPoint) BigWorld.player().positionControl.followCamera(False) self.__cameraUpdate() self.delayCallback(0.01, self.__cameraUpdate) self.__needReset = 1 return def disable(self): self.__scrollSmoother.stop() if self.__aimingSystem is not None: self.__aimingSystem.disable() self.stopCallback(self.__cameraUpdate) self.__switchers.clear() self.__positionOscillator.reset() return def teleport(self, pos): self.__aimingSystem.updateTargetPos(pos) self.update(0.0, 0.0, 0.0) def getDistRatio(self): minDist, maxDist = self._cfg['distRange'] return (self.__desiredCamDist - minDist) / (maxDist - minDist) def getCurrentCamDist(self): return self.__desiredCamDist def getCamDistRange(self): return self._cfg['distRange'] def getCamTransitionDist(self): return self._cfg['transitionDist'] def update(self, dx, dy, dz, updateByKeyboard=False): self.__curSense = self._cfg[ 'keySensitivity'] if updateByKeyboard else self._cfg['sensitivity'] self.__autoUpdatePosition = updateByKeyboard self.__dxdydz = Vector3(dx if not self._cfg['horzInvert'] else -dx, dy if not self._cfg['vertInvert'] else -dy, dz) def applyImpulse(self, position, impulse, reason=ImpulseReason.ME_HIT): adjustedImpulse, noiseMagnitude = self.__dynamicCfg.adjustImpulse( impulse, reason) impulseFlatDir = Vector3(adjustedImpulse.x, 0, adjustedImpulse.z) impulseFlatDir.normalise() impulseLocal = self.__sourceMatrix.applyVector( impulseFlatDir * (-1 * adjustedImpulse.length)) self.__positionOscillator.applyImpulse(impulseLocal) self.__applyNoiseImpulse(noiseMagnitude) def applyDistantImpulse(self, position, impulseValue, reason=ImpulseReason.ME_HIT): if reason != ImpulseReason.SPLASH and reason != ImpulseReason.PROJECTILE_HIT: return impulse = BigWorld.player().getOwnVehiclePosition() - position distance = impulse.length if distance <= 1.0: distance = 1.0 impulse.normalise() if reason == ImpulseReason.PROJECTILE_HIT: if not cameras.isPointOnScreen(position): return distance = 1.0 impulse *= impulseValue / distance self.applyImpulse(position, impulse, reason) def writeUserPreferences(self): ds = Settings.g_instance.userPrefs if not ds.has_key(Settings.KEY_CONTROL_MODE): ds.write(Settings.KEY_CONTROL_MODE, '') ucfg = self._userCfg ds = ds[Settings.KEY_CONTROL_MODE] ds.writeBool('artyMode/camera/horzInvert', ucfg['horzInvert']) ds.writeBool('artyMode/camera/vertInvert', ucfg['vertInvert']) ds.writeFloat('artyMode/camera/keySensitivity', ucfg['keySensitivity']) ds.writeFloat('artyMode/camera/sensitivity', ucfg['sensitivity']) ds.writeFloat('artyMode/camera/scrollSensitivity', ucfg['scrollSensitivity']) ds.writeFloat('artyMode/camera/camDist', self._cfg['camDist']) def __applyNoiseImpulse(self, noiseMagnitude): noiseImpulse = math_utils.RandomVectors.random3Flat(noiseMagnitude) self.__positionNoiseOscillator.applyImpulse(noiseImpulse) def __calculateAimOffset(self, aimWorldPos): if not self.isAimOffsetEnabled: return Vector2(0.0, 0.0) replayCtrl = BattleReplay.g_replayCtrl if replayCtrl.isPlaying and replayCtrl.isControllingCamera: aimOffset = replayCtrl.getAimClipPosition() else: proj = BigWorld.projection() aimLocalPos = Matrix(self.__cam.matrix).applyPoint(aimWorldPos) if aimLocalPos.z < 0: aimLocalPos.z = max(0.0, proj.nearPlane - _OFFSET_FROM_NEAR_PLANE) aimWorldPos = Matrix( self.__cam.invViewMatrix).applyPoint(aimLocalPos) aimOffset = cameras.projectPoint(aimWorldPos) aimOffset = Vector2(math_utils.clamp(-0.95, 0.95, aimOffset.x), math_utils.clamp(-0.95, 0.95, aimOffset.y)) if replayCtrl.isRecording: replayCtrl.setAimClipPosition(aimOffset) return aimOffset def __handleMovement(self): replayCtrl = BattleReplay.g_replayCtrl if replayCtrl.isPlaying: if self.__needReset != 0: if self.__needReset > 1: from helpers import isPlayerAvatar player = BigWorld.player() if isPlayerAvatar(): if player.inputHandler.ctrl is not None: player.inputHandler.ctrl.resetGunMarkers() self.__needReset = 0 else: self.__needReset += 1 if replayCtrl.isControllingCamera: self.__aimingSystem.updateTargetPos( replayCtrl.getGunRotatorTargetPoint()) else: self.__aimingSystem.handleMovement( self.__dxdydz.x * self.__curSense, -self.__dxdydz.y * self.__curSense) if self.__dxdydz.x != 0 or self.__dxdydz.y != 0 or self.__dxdydz.z != 0: self.__needReset = 2 else: self.__aimingSystem.handleMovement( self.__dxdydz.x * self.__curSense, -self.__dxdydz.y * self.__curSense) return def __getCameraDirection(self): direction = Vector3() direction.setPitchYaw(self.__rotation, self.__aimingSystem.direction.yaw) direction.normalise() return direction def __getDesiredCameraDistance(self): distRange = self.__switchersDistRange() self.__desiredCamDist -= self.__dxdydz.z * self.__curSense self.__desiredCamDist = math_utils.clamp(distRange[0], distRange[1], self.__desiredCamDist) self.__desiredCamDist = self.__aimingSystem.overrideCamDist( self.__desiredCamDist) self._cfg['camDist'] = self.__camDist self.__scrollSmoother.moveTo(self.__desiredCamDist, distRange) return self.__desiredCamDist def __updateTrajectoryDrawer(self): shotDescr = BigWorld.player().getVehicleDescriptor().shot BigWorld.wg_trajectory_drawer().setParams( shotDescr.maxDistance, Vector3(0, -shotDescr.gravity, 0), self.__aimOffset) def __updateTime(self): curTime = BigWorld.timeExact() deltaTime = curTime - self.__prevTime self.__prevTime = curTime return deltaTime def __choosePitchLevel(self, aimPoint): useHighPitch = (aimPoint - self.__aimingSystem.hitPoint ).lengthSquared > self._cfg['highPitchThresholdSq'] if useHighPitch: useHighPitch = self.__positionHysteresis.check( aimPoint) or self.__timeHysteresis.check(self.__prevTime) else: self.__positionHysteresis.update(aimPoint) self.__timeHysteresis.update(self.__prevTime) return useHighPitch def __getCollisionTestOrigin(self, aimPoint, direction): distRange = self.__switchersDistRange() vehiclePosition = BigWorld.player().getVehicleAttached().position collisionTestOrigin = Vector3(vehiclePosition) if direction.x * direction.x > direction.z * direction.z and not math_utils.almostZero( direction.x): collisionTestOrigin.y = direction.y / direction.x * ( vehiclePosition.x - aimPoint.x) + aimPoint.y elif not math_utils.almostZero(direction.z): collisionTestOrigin.y = direction.y / direction.z * ( vehiclePosition.z - aimPoint.z) + aimPoint.y else: collisionTestOrigin = aimPoint - direction.scale( (distRange[1] - distRange[0]) / 2.0) LOG_WARNING( "Can't find point on direction ray. Using half point as collision test origin" ) return collisionTestOrigin def __resolveCollisions(self, aimPoint, distance, direction): distRange = self.__switchersDistRange() collisionDist = 0.0 collisionTestOrigin = self.__getCollisionTestOrigin( aimPoint, direction) sign = copysign( 1.0, distance * distance - (aimPoint - collisionTestOrigin).lengthSquared) srcPoint = collisionTestOrigin endPoint = aimPoint - direction.scale( distance + sign * (distRange[0] + _SEARCH_COLLISION_DEPTH)) collision = collideDynamicAndStatic( srcPoint, endPoint, (BigWorld.player().playerVehicleID, )) if collision: collisionDistance = (aimPoint - collision[0]).length collisionDist = collisionDistance - sign * distRange[0] if sign * (collisionDistance - distance) < distRange[0]: distance = collisionDist if math_utils.almostZero(self.__rotation): srcPoint = aimPoint - direction.scale(distance) endPoint = aimPoint collision = collideDynamicAndStatic( srcPoint, endPoint, (BigWorld.player().playerVehicleID, )) if collision: self.__aimingSystem.aimPoint = collision[0] if collision[1]: self.__positionHysteresis.update(aimPoint) self.__timeHysteresis.update(self.__prevTime) return collisionDist def __calculateIdealState(self, deltaTime): aimPoint = self.__aimingSystem.aimPoint direction = self.__aimingSystem.direction impactPitch = max(direction.pitch, self._cfg['minimalPitch']) self.__rotation = max(self.__rotation, impactPitch) distRange = self.__switchersDistRange() distanceCurSq = ( aimPoint - BigWorld.player().getVehicleAttached().position).lengthSquared distanceMinSq = distRange[0]**2.0 forcedPitch = impactPitch if distanceCurSq < distanceMinSq: forcedPitch = atan2(sqrt(distanceMinSq - distanceCurSq), sqrt(distanceCurSq)) angularShift = self._cfg['angularSpeed'] * deltaTime angularShift = angularShift if self.__choosePitchLevel( aimPoint) else -angularShift minPitch = max(forcedPitch, impactPitch) maxPitch = max(forcedPitch, self._cfg['maximalPitch']) self.__rotation = math_utils.clamp(minPitch, maxPitch, self.__rotation + angularShift) desiredDistance = self.__getDesiredCameraDistance() cameraDirection = self.__getCameraDirection() collisionDist = self.__resolveCollisions(aimPoint, desiredDistance, cameraDirection) collisionDist = max(distRange[0], collisionDist) desiredDistance = self.__scrollSmoother.update(deltaTime) rotation = Vector3(cameraDirection.yaw, -cameraDirection.pitch, 0.0) return (rotation, desiredDistance, collisionDist) def __interpolateStates(self, deltaTime, rotation, desiredDistance, collisionDist): lerpParam = math_utils.clamp( 0.0, 1.0, deltaTime * self._cfg['interpolationSpeed']) collisionLerpParam = math_utils.clamp( 0.0, 1.0, deltaTime * self._cfg['distInterpolationSpeed']) self.__sourceMatrix = slerp(self.__sourceMatrix, rotation, lerpParam) camDirection = Vector3() camDirection.setPitchYaw(-self.__sourceMatrix.pitch, self.__sourceMatrix.yaw) camDirection.normalise() self.__camViewPoint = math_utils.lerp(self.__camViewPoint, self.__aimingSystem.aimPoint, lerpParam) self.__collisionDist = math_utils.lerp(self.__collisionDist, collisionDist, collisionLerpParam) desiredDistance = max(desiredDistance, self.__collisionDist) self.__targetMatrix.translation = self.__camViewPoint - camDirection.scale( desiredDistance) return (self.__sourceMatrix, self.__targetMatrix) def __cameraUpdate(self): deltaTime = self.__updateTime() self.__aimOffset = self.__calculateAimOffset( self.__aimingSystem.aimPoint) self.__handleMovement() aimPoint = Vector3(self.__aimingSystem.aimPoint) self.__updateTrajectoryDrawer() rotation, desiredDistance, collisionDist = self.__calculateIdealState( deltaTime) self.__interpolateStates(deltaTime, math_utils.createRotationMatrix(rotation), desiredDistance, collisionDist) self.__camDist = aimPoint - self.__targetMatrix.translation self.__camDist = self.__camDist.length self.__cam.source = self.__sourceMatrix self.__cam.target.b = self.__targetMatrix self.__cam.pivotPosition = Vector3(0, 0, 0) if aimPoint.distSqrTo(self.__prevAimPoint) > 0.010000000000000002: BigWorld.player().positionControl.moveTo(aimPoint) self.__prevAimPoint = aimPoint self.__updateOscillator(deltaTime) self.__aimingSystem.update(deltaTime) if self.__onChangeControlMode is not None and self.__switchers.needToSwitch( self.__dxdydz.z, self.__desiredCamDist, self._cfg['distRange'][0], self._cfg['distRange'][1], self._cfg['transitionDist']): self.__onChangeControlMode(*self.__switchers.getSwitchParams()) if not self.__transitionEnabled and self.__desiredCamDist - TRANSITION_DIST_HYSTERESIS <= self._cfg[ 'transitionDist']: self.__transitionEnabled = True self.__enableSwitchers(False) if not self.__autoUpdatePosition: self.__dxdydz = Vector3(0, 0, 0) return 0.01 def __updateOscillator(self, deltaTime): if ArtyCamera.isCameraDynamic(): self.__positionOscillator.update(deltaTime) self.__positionNoiseOscillator.update(deltaTime) else: self.__positionOscillator.reset() self.__positionNoiseOscillator.reset() self.__cam.target.a = math_utils.createTranslationMatrix( self.__positionOscillator.deviation + self.__positionNoiseOscillator.deviation) def __switchersDistRange(self): distRange = self._cfg['distRange'] if self.__switchers.isEnabled(): distRange = self.__switchers.getDistLimitationForSwitch( distRange[0], distRange[1], self._cfg['transitionDist']) return distRange def _readConfigs(self, dataSec): if not dataSec: LOG_WARNING( 'Invalid section <artyMode/camera> in avatar_input_handler.xml' ) super(ArtyCamera, self)._readConfigs(dataSec) dynamicSection = dataSec['dynamics'] self.__dynamicCfg.readImpulsesConfig(dynamicSection) self.__positionOscillator = createOscillatorFromSection( dynamicSection['oscillator'], False) self.__positionNoiseOscillator = createOscillatorFromSection( dynamicSection['randomNoiseOscillatorFlat']) def _readBaseCfg(self, dataSec): bcfg = self._baseCfg bcfg['keySensitivity'] = readFloat(dataSec, 'keySensitivity', 0.005, 10.0, 0.025) bcfg['sensitivity'] = readFloat(dataSec, 'sensitivity', 0.005, 10.0, 0.025) bcfg['scrollSensitivity'] = readFloat(dataSec, 'scrollSensitivity', 0.005, 10.0, 0.025) bcfg['angularSpeed'] = readFloat(dataSec, 'angularSpeed', pi / 720.0, pi / 0.5, pi / 360.0) bcfg['distRange'] = readVec2(dataSec, 'distRange', (1.0, 1.0), (10000.0, 10000.0), (2.0, 30.0)) bcfg['transitionDist'] = readFloat(dataSec, 'transitionDist', 1.0, 10000.0, 60.0) bcfg['minimalPitch'] = readFloat(dataSec, 'minimalPitch', pi / 36.0, pi / 3.0, pi / 18.0) bcfg['maximalPitch'] = readFloat(dataSec, 'maximalPitch', pi / 6.0, pi / 3.0, pi / 3.5) bcfg['interpolationSpeed'] = readFloat(dataSec, 'interpolationSpeed', 0.0, 100.0, 5.0) bcfg['distInterpolationSpeed'] = readFloat(dataSec, 'distInterpolationSpeed', 0.0, 10.0, 5.0) bcfg['highPitchThreshold'] = readFloat(dataSec, 'highPitchThreshold', 0.1, 10.0, 3.0) bcfg['hTimeThreshold'] = readFloat(dataSec, 'hysteresis/timeThreshold', 0.0, 10.0, 0.5) bcfg['hPositionThreshold'] = readFloat(dataSec, 'hysteresis/positionThreshold', 0.0, 100.0, 7.0) bcfg['scrollSmoothingTime'] = readFloat(dataSec, 'scrollSmoothingTime', 0.0, 1.0, 0.3) def _readUserCfg(self): ucfg = self._userCfg dataSec = Settings.g_instance.userPrefs[Settings.KEY_CONTROL_MODE] if dataSec is not None: dataSec = dataSec['artyMode/camera'] ucfg['horzInvert'] = False ucfg['vertInvert'] = False ucfg['keySensitivity'] = readFloat(dataSec, 'keySensitivity', 0.0, 10.0, 1.0) ucfg['sensitivity'] = readFloat(dataSec, 'sensitivity', 0.0, 10.0, 1.0) ucfg['scrollSensitivity'] = readFloat(dataSec, 'scrollSensitivity', 0.0, 10.0, 1.0) ucfg['camDist'] = readFloat(dataSec, 'camDist', 0.0, 60.0, 0.0) return def _makeCfg(self): bcfg = self._baseCfg ucfg = self._userCfg cfg = self._cfg cfg['keySensitivity'] = bcfg['keySensitivity'] cfg['sensitivity'] = bcfg['sensitivity'] cfg['scrollSensitivity'] = bcfg['scrollSensitivity'] cfg['distRange'] = bcfg['distRange'] cfg['transitionDist'] = bcfg['transitionDist'] cfg['angularSpeed'] = bcfg['angularSpeed'] cfg['minimalPitch'] = bcfg['minimalPitch'] cfg['maximalPitch'] = bcfg['maximalPitch'] cfg['interpolationSpeed'] = bcfg['interpolationSpeed'] cfg['distInterpolationSpeed'] = bcfg['distInterpolationSpeed'] cfg['highPitchThresholdSq'] = bcfg['highPitchThreshold'] * bcfg[ 'highPitchThreshold'] cfg['hTimeThreshold'] = bcfg['hTimeThreshold'] cfg['hPositionThresholdSq'] = bcfg['hPositionThreshold'] * bcfg[ 'hPositionThreshold'] cfg['scrollSmoothingTime'] = bcfg['scrollSmoothingTime'] cfg['keySensitivity'] *= ucfg['keySensitivity'] cfg['sensitivity'] *= ucfg['sensitivity'] cfg['scrollSensitivity'] *= ucfg['scrollSensitivity'] cfg['camDist'] = ucfg['camDist'] cfg['horzInvert'] = ucfg['horzInvert'] cfg['vertInvert'] = ucfg['vertInvert'] def _handleSettingsChange(self, diff): super(ArtyCamera, self)._handleSettingsChange(diff) if SPGAim.AUTO_CHANGE_AIM_MODE in diff: self.__enableSwitchers() if GAME.SCROLL_SMOOTHING in diff: self.__scrollSmoother.setIsEnabled( self.settingsCore.getSetting(GAME.SCROLL_SMOOTHING)) def _updateSettingsFromServer(self): super(ArtyCamera, self)._updateSettingsFromServer() if self.settingsCore.isReady: self.__enableSwitchers() self.__scrollSmoother.setIsEnabled( self.settingsCore.getSetting(GAME.SCROLL_SMOOTHING)) def __enableSwitchers(self, updateTransitionEnabled=True): if updateTransitionEnabled and self.__desiredCamDist - TRANSITION_DIST_HYSTERESIS >= self._cfg[ 'transitionDist']: self.__transitionEnabled = False if self.settingsCore.isReady: self.__switchers.setIsEnabled( self.settingsCore.getSetting(SPGAim.AUTO_CHANGE_AIM_MODE) and self.__transitionEnabled)
def new_showDamageFromShot(self, attackerID, points, effectsIndex, damageFactor, *a, **k): if LOG_EVENTS and attackerID > 0: player = BigWorld.player() #Initial info points_count = len(points) if points else 0 timeLeft, timeLeftSec = getTimeLeft() eventInfo = [ '%s' % player.arenaUniqueID, timeLeft, timeLeftSec, '"Vehicle.showDamageFromShot"', '%s' % player.arena.vehicles[self.id].get('accountDBID', '-'), '%s' % player.arena.vehicles[attackerID].get('accountDBID', '-'), json.dumps({ 'points': points_count, 'effectsIndex': effectsIndex, 'damageFactor': damageFactor }) ] #Decode info shellInfo = {} for shot in player.arena.vehicles[attackerID][ 'vehicleType'].gun.shots: if effectsIndex == shot.shell.effectsIndex: shellInfo['name'] = shot.shell.name shellInfo['kind'] = shellTypeAbb(shot.shell.kind) shellInfo['damage'] = str(shot.shell.damage) shellInfo['caliber'] = shot.shell.caliber shellInfo['piercingPower'] = str(shot.piercingPower) shellInfo['speed'] = round(shot.speed / 0.8, 3) shellInfo['gravity'] = round(shot.gravity / 0.64, 3) shellInfo['maxDistance'] = shot.maxDistance if shot.shell.kind == 'HIGH_EXPLOSIVE': shellInfo[ 'explosionRadius'] = shot.shell.type.explosionRadius break eventInfo.append(json.dumps(shellInfo) if shellInfo else '') maxHitEffectCode, decodedPoints, maxDamagedComponent = DamageFromShotDecoder.decodeHitPoints( points, self.appearance.collisions) hasPiercedHit = DamageFromShotDecoder.hasDamaged(maxHitEffectCode) attacker = BigWorld.entities.get(attackerID, None) attackerPos = attacker.position if isinstance( attacker, Vehicle ) and attacker.inWorld and attacker.isStarted else player.arena.positions.get( attackerID) eventInfo.append( json.dumps({ 'maxHitEffectCode': VEHICLE_HIT_EFFECT_NAMES.get(maxHitEffectCode), 'maxDamagedComponent': maxDamagedComponent, 'hasPiercedHit': hasPiercedHit, 'distance': round(self.position.distTo(attackerPos), 3) if attackerPos else None, 'hitPoints': [{ 'componentName': point.componentName, 'hitEffectGroup': point.hitEffectGroup } for point in decodedPoints] if decodedPoints else None })) for num, encodedPoint in enumerate(points, 1): hitsInfo = [] #[[Dir1-Layer1, ...], [Dir2-Layer1, ...], ...] hitsScheme = None compIdx, hitEffectCode, startPoint, endPoint = DamageFromShotDecoder.decodeSegment( encodedPoint, self.appearance.collisions, TankPartIndexes.ALL[-1]) if compIdx >= 0 and startPoint != endPoint: convertedCompIdx = DamageFromShotDecoder.convertComponentIndex( compIdx) bbox = self.appearance.collisions.getBoundingBox( convertedCompIdx) width, height, depth = (bbox[1] - bbox[0]) / 256.0 if COLLIDE_MULTI: if COLLIDE_SCHEME == 'hexahedron': hitsScheme = _CSHexahedron(width, height, depth, COLLIDE_SCALE) elif COLLIDE_SCHEME == 'cross': hitsScheme = _CSCross(width, height, depth, COLLIDE_SCALE) else: hitsScheme = _CSCenter() else: hitsScheme = _CSCenter() compMatrix = Matrix( self.appearance.compoundModel.node( TankPartIndexes.getName(convertedCompIdx))) firstHitDir = endPoint - startPoint firstHitDir.normalise() firstHitDir = compMatrix.applyVector(firstHitDir) firstHitPos = compMatrix.applyPoint(startPoint) for direction in hitsScheme.directions: hitInfo = [] collisions = self.appearance.collisions.collideAllWorld( firstHitPos - firstHitDir.scale(COLLIDE_INDENT) + direction, firstHitPos + firstHitDir.scale(COLLIDE_LENGTH) + direction) if collisions: base = None testPointAdded = collidePointAdded = False for collision in collisions: if collision[3] in TankPartIndexes.ALL: if base is None: base = collision[0] if not testPointAdded: if collision[0] > COLLIDE_INDENT: hitInfo.append( 'TestPoint%s(distance=%s, tankPart=%s)' % (num if points_count > 1 else '', round(COLLIDE_INDENT - base, 4), TankPartIndexes.getName( convertedCompIdx))) testPointAdded = True material = self.getMatinfo( collision[3], collision[2]) hitInfo.append({ 'distance': round(collision[0] - base, 4), 'angleCos': round(collision[1], 4), 'tankPart': TankPartIndexes.getName(collision[3]), 'armor': round(material.armor, 4) if material else None }) if not collidePointAdded: collidePointAdded = True if material and material.vehicleDamageFactor > 0 and collision[ 3] in (TankPartIndexes.HULL, TankPartIndexes.TURRET): break if collidePointAdded: if not testPointAdded and base is not None: hitInfo.append( 'TestPoint%s(distance=%s, tankPart=%s)' % (num if points_count > 1 else '', round(COLLIDE_INDENT - base, 4), TankPartIndexes.getName( convertedCompIdx))) hitsInfo.append(hitInfo) eventInfo.append(json.dumps('%s: %s' % ('TestPoint%d' % num if points_count > 1 else 'layers' if hitsScheme.NAME == 'center' else 'TestPoint', \ hitsScheme.format(hitsInfo[0] if hitsScheme.NAME == 'center' else hitsInfo) if hitsScheme else '[]'))) printStrings(LOG_EVENTS_FILENAME, eventInfo)