Jump to content
Korean Random
kharlashkin

Модернизация прицела

Recommended Posts

Доброе время суток всем форумчанам и гостям!

 

Интересуюсь следующей возможностью (может кто встречал или подскажет направление) - хочется для более комфортной стрельбы геймпадом увеличить точку прицела в игре до "пятна", например как в Crysis.

post-19155-0-79926100-1404905117_thumb.jpg

 

P.S. Требуется вот для чего, на любой дистанции если нет "подсветки" контура врага/союзника, расчет выстрела снаряда делается отдельной формулой (может я не прав - поправьте меня). В случае пятна прицела (не точки) танк будет подсвечиваться даже когда край пятна попадет на контуры, соответственно формула полета снаряда применяется, соответственно будет проще попадать, как бонус можно попробовать сделать автодоводку прицела ;)

Edited by kharlashkin

Share this post


Link to post

Short link
Share on other sites

Как вариант - декомпильнуть дефолтный прицел в Sothink, найти пнг-шку или спрайт с точкой (в дефолте присутствует)    и намалевать чего то своё

Share this post


Link to post

Short link
Share on other sites

Как вариант - декомпильнуть дефолтный прицел в Sothink, найти пнг-шку или спрайт с точкой (в дефолте присутствует)    и намалевать чего то своё

Не-не-не, мне не нужна картинка :) Нужно поведение прицела, как для консольных игр. Я наверное не совсем внятно описал что к чему.

 

Есть так называемый круг сведения, т.е. случайным образом снаряд летит в любую точку внутри этого круга.

Есть так называемый прицел, который по сути является точкой по середине экрана.

Существуют формулы полета снаряда, и если прицел наведен на танк и танк подсвечен - в формулу добавляется расстояние до цели.

 

Необходимо каким-то образом подсвечивать танк, когда он находиться в кругу сведения, ведь тогда будет в формуле учитываться расстояние до этого танка и с большей вероятностью снаряд влетит в танк (чем если целиться рядом с противником, особенно когда он не подсвечен).

 

Учитывая клиент-серверную архитектуру игры, наверное это невозможно, но я - я ж просто спрашиваю.

Edited by kharlashkin

Share this post


Link to post

Short link
Share on other sites

Не-не-не, мне не нужна картинка :) Нужно поведение прицела, как для консольных игр. Я наверное не совсем внятно описал что к чему.

 

Есть так называемый круг сведения, т.е. случайным образом снаряд летит в любую точку внутри этого круга.

Есть так называемый прицел, который по сути является точкой по середине экрана.

Существуют формулы полета снаряда, и если прицел наведен на танк и танк подсвечен - в формулу добавляется расстояние до цели.

 

Необходимо каким-то образом подсвечивать танк, когда он находиться в кругу сведения, ведь тогда будет в формуле учитываться расстояние до этого танка и с большей вероятностью снаряд влетит в танк (чем если целиться рядом с противником, особенно когда он не подсвечен).

 

Учитывая клиент-серверную архитектуру игры, наверное это невозможно, но я - я ж просто спрашиваю.

я понимаю чего вы хотите т это на самом деле интересно, дествительно, может есть гений, который это воплотит?

Share this post


Link to post

Short link
Share on other sites

Люди добрые, разбираю по-полочкам код прицеливания в игре, а именно папку "X:\Games\World_of_Tanks\res\scripts\client\avatarinputhandler\aimingsystems", прошу помощи...

Согласиться ли кто прокомментировать код?

'__init__.pyc'

import BigWorld
import Math
from Math import Vector3, Matrix
import math
from AvatarInputHandler import mathUtils
from AvatarInputHandler.mathUtils import MatrixProviders
from ProjectileMover import collideDynamicAndStatic
from debug_utils import LOG_CODEPOINT_WARNING

class IAimingSystem(object):
    matrix = property(lambda self: self._matrix)

    def __init__(self):
        self._matrix = mathUtils.createIdentityMatrix()

    def destroy(self):
        pass

    def enable(self, targetPos):
        pass

    def disable(self):
        pass

    def getDesiredShotPoint(self):
        pass

    def handleMovement(self, dx, dy):
        pass

    def update(self, deltaTime):
        pass


def getTurretJointMat(vehicleTypeDescriptor, vehicleMatrix, turretYaw = 0.0):
    turretOffset = vehicleTypeDescriptor.chassis['hullPosition'] + vehicleTypeDescriptor.hull['turretPositions'][0]
    turretJointMat = mathUtils.createRTMatrix(Vector3(turretYaw, 0, 0), turretOffset)
    turretJointMat.postMultiply(vehicleMatrix)
    return turretJointMat


def getGunJointMat(vehicleTypeDescriptor, turretMatrix, gunPitch):
    gunOffset = vehicleTypeDescriptor.turret['gunPosition']
    gunMat = mathUtils.createRTMatrix(Vector3(0, gunPitch, 0), gunOffset)
    gunMat.postMultiply(turretMatrix)
    return gunMat


def getPlayerTurretMats(turretYaw = 0.0, gunPitch = 0.0):
    player = BigWorld.player()
    vehicleTypeDescriptor = player.vehicleTypeDescriptor
    vehicleMatrix = player.getOwnVehicleMatrix()
    turretMat = getTurretJointMat(vehicleTypeDescriptor, vehicleMatrix, turretYaw)
    return (turretMat, getGunJointMat(vehicleTypeDescriptor, turretMat, gunPitch))


def getPlayerGunMat(turretYaw = 0.0, gunPitch = 0.0):
    return getPlayerTurretMats(turretYaw, gunPitch)[1]


def getTurretMatrixProvider(vehicleTypeDescriptor, vehicleMatrixProvider, turretYawMatrixProvider):
    turretOffset = vehicleTypeDescriptor.chassis['hullPosition'] + vehicleTypeDescriptor.hull['turretPositions'][0]
    return MatrixProviders.product(turretYawMatrixProvider, MatrixProviders.product(mathUtils.createTranslationMatrix(turretOffset), vehicleMatrixProvider))


def getGunMatrixProvider(vehicleTypeDescriptor, turretMatrixProvider, gunPitchMatrixProvider):
    gunOffset = vehicleTypeDescriptor.turret['gunPosition']
    return MatrixProviders.product(gunPitchMatrixProvider, MatrixProviders.product(mathUtils.createTranslationMatrix(gunOffset), turretMatrixProvider))


def getTurretYawGunPitch(vehTypeDescr, vehicleMatrix, targetPos, compensateGravity = False):
    turretOffs = vehTypeDescr.hull['turretPositions'][0] + vehTypeDescr.chassis['hullPosition']
    gunOffs = vehTypeDescr.turret['gunPosition']
    speed = vehTypeDescr.shot['speed']
    gravity = vehTypeDescr.shot['gravity'] if not compensateGravity else 0.0
    return BigWorld.wg_getShotAngles(turretOffs, gunOffs, vehicleMatrix, speed, gravity, 0.0, 0.0, targetPos, False)


def getDesiredShotPoint(start, dir, onlyOnGround = False, isStrategicMode = False):
    end = start + dir.scale(10000.0)
    if isStrategicMode:
        point1 = __collideStaticOnly(start, end)
        point2 = collideDynamicAndStatic(start, end, (BigWorld.player().playerVehicleID,), skipGun=isStrategicMode)
        if point1 is None or point2 is None:
            point = None
        else:
            dir = Math.Vector3(point2[0]) - Math.Vector3(point1[0])
            point = (Math.Vector3(point1[0]) + dir.scale(0.5), None)
    else:
        point = collideDynamicAndStatic(start, end, (BigWorld.player().playerVehicleID,), skipGun=isStrategicMode)
    if point is not None:
        return point[0]
    elif not onlyOnGround:
        return shootInSkyPoint(start, dir)
    else:
        return
        return


def shootInSkyPoint(startPos, dir):
    dirFromCam = dir
    start = startPos
    dirFromCam.normalise()
    vehicle = BigWorld.player().vehicle
    if vehicle is not None and vehicle.inWorld and vehicle.isStarted:
        shotPos = Math.Vector3(vehicle.appearance.modelsDesc['gun']['model'].position)
        shotDesc = vehicle.typeDescriptor.shot
    else:
        type = BigWorld.player().arena.vehicles[BigWorld.player().playerVehicleID]['vehicleType']
        shotPos = BigWorld.player().getOwnVehiclePosition()
        shotPos += type.hull['turretPositions'][0] + type.turret['gunPosition']
        shotDesc = type.shot
    dirAtCam = shotPos - start
    dirAtCam.normalise()
    cosAngle = dirAtCam.dot(dirFromCam)
    a = shotDesc['maxDistance']
    b = shotPos.distTo(start)
    try:
        dist = b * cosAngle + math.sqrt(b * b * (cosAngle * cosAngle - 1) + a * a)
    except:
        dist = shotDesc['maxDistance']
        LOG_CODEPOINT_WARNING()

    if dist < 0.0:
        dist = shotDesc['maxDistance']
    finalPoint = start + dirFromCam.scale(dist)
    intersecPoint = BigWorld.player().arena.collideWithSpaceBB(start, finalPoint)
    if intersecPoint is not None:
        finalPoint = intersecPoint
    return finalPoint


def __collideStaticOnly(startPoint, endPoint):
    res = None
    testRes = BigWorld.wg_collideSegment(BigWorld.player().spaceID, startPoint, endPoint, 128)
    if testRes is not None:
        res = (testRes[0], None)
    return res 

 

'ArcadeAimingSystem.pyc'

import BigWorld
import Math
from Math import Vector3, Matrix
import functools
import math
from AvatarInputHandler import mathUtils, AimingSystems, cameras
from AvatarInputHandler.AimingSystems import IAimingSystem
from ProjectileMover import collideDynamic
from debug_utils import LOG_WARNING
import gun_rotation_shared

class ArcadeAimingSystem(IAimingSystem):

    def __setDistanceFromFocus(self, value):
        shotPoint = self.getThirdPersonShotPoint()
        self.__cursor.distanceFromFocus = value
        posOnVehicleProv = self.positionAboveVehicleProv.value
        posOnVehicle = Vector3(posOnVehicleProv.x, posOnVehicleProv.y, posOnVehicleProv.z)
        camPos = self.matrix.translation
        triBase = camPos - posOnVehicle
        pivotToTarget = shotPoint - posOnVehicle
        camPosToTarget = shotPoint - camPos
        if triBase.dot(camPosToTarget) * triBase.dot(pivotToTarget) > 0:
            if self.__shotPointCalculator is not None:
                self.__adjustFocus()
            else:
                self.focusOnPos(shotPoint)
        return

    def __setVehicleMProv(self, value):
        self.__vehicleMProv = value
        self.__cursor.base = value

    def __setYaw(self, value):
        self.__cursor.yaw = value
        if self.__cursor.yaw > 2.0 * math.pi:
            self.__cursor.yaw -= 2.0 * math.pi
        elif self.__cursor.yaw < -2.0 * math.pi:
            self.__cursor.yaw += 2.0 * math.pi

    def __setPitch(self, value):
        self.__cursor.pitch = mathUtils.clamp(self.__anglesRange[0], self.__anglesRange[1], value)

    def __setAimMatrix(self, aimMatrix):
        self.__aimMatrix = aimMatrix
        self.__setDistanceFromFocus(self.distanceFromFocus)

    vehicleMProv = property(lambda self: self.__vehicleMProv, __setVehicleMProv)
    positionAboveVehicleProv = property(lambda self: self.__cursor.positionAboveBaseProvider)
    distanceFromFocus = property(lambda self: self.__cursor.distanceFromFocus, __setDistanceFromFocus)
    aimMatrix = property(lambda self: self.__aimMatrix, __setAimMatrix)
    yaw = property(lambda self: self.__cursor.yaw, __setYaw)
    pitch = property(lambda self: self.__cursor.pitch, __setPitch)

    def __init__(self, vehicleMProv, heightAboveTarget, focusRadius, aimMatrix, anglesRange, enableSmartShotPointCalc = True):
        IAimingSystem.__init__(self)
        self.__aimMatrix = aimMatrix
        self.__vehicleMProv = vehicleMProv
        self.__anglesRange = anglesRange
        self.__cursor = BigWorld.ThirdPersonProvider()
        self.__cursor.base = vehicleMProv
        self.__cursor.heightAboveBase = heightAboveTarget
        self.__cursor.focusRadius = focusRadius
        self.__shotPointCalculator = ShotPointCalculatorPlanar() if enableSmartShotPointCalc else None
        return

    def getPivotSettings(self):
        return (self.__cursor.heightAboveBase, self.__cursor.focusRadius)

    def setPivotSettings(self, heightAboveBase, focusRadius):
        self.__cursor.heightAboveBase = heightAboveBase
        self.__cursor.focusRadius = focusRadius

    def destroy(self):
        IAimingSystem.destroy(self)

    def enable(self, targetPos, turretYaw = None, gunPitch = None):
        if targetPos is not None:
            self.focusOnPos(targetPos)
            if turretYaw is not None and gunPitch is not None:
                self.__adjustFocus((turretYaw, gunPitch))
        return

    def __adjustFocus(self, yawPitch = None):
        if self.__shotPointCalculator is None:
            return
        else:
            scanStart, scanDir = self.__getScanRay()
            self.focusOnPos(self.__shotPointCalculator.focusAtPos(scanStart, scanDir, yawPitch))
            return

    def disable(self):
        pass

    def setModelsToCollideWith(self, models):
        self.__cursor.setModelsToCollideWith(models)

    def focusOnPos(self, preferredPos):
        vehPos = Matrix(self.__vehicleMProv).translation
        posOnVehicle = vehPos + Vector3(0, self.__cursor.heightAboveBase, 0)
        self.yaw = (preferredPos - vehPos).yaw
        xzDir = Vector3(self.__cursor.focusRadius * math.sin(self.__cursor.yaw), 0, self.__cursor.focusRadius * math.cos(self.__cursor.yaw))
        pivotPos = posOnVehicle + xzDir
        self.pitch = self.__calcPitchAngle(self.__cursor.distanceFromFocus, preferredPos - pivotPos)
        self.__cursor.update(True)
        aimMatrix = self.__getLookToAimMatrix()
        aimMatrix.postMultiply(self.__cursor.matrix)
        self._matrix.set(aimMatrix)

    def __calcPitchAngle(self, distanceFromFocus, dir):
        fov = BigWorld.projection().fov
        near = BigWorld.projection().nearPlane
        yLength = near * math.tan(fov * 0.5)
        alpha = -self.__aimMatrix.pitch
        a = distanceFromFocus
        b = dir.length
        A = 2.0 * a * math.cos(alpha)
        B = a * a - b * b
        D = A * A - 4.0 * B
        if D > 0.0:
            c1 = (A + math.sqrt(D)) * 0.5
            c2 = (A - math.sqrt(D)) * 0.5
            c = c1 if c1 > c2 else c2
            cosValue = (a * a + b * b - c * c) / (2.0 * a * b) if a * b != 0.0 else 2.0
            if cosValue < -1.0 or cosValue > 1.0:
                LOG_WARNING('Invalid arg for acos: %f; distanceFromFocus: %f, dir: %s' % (cosValue, distanceFromFocus, dir))
                return -dir.pitch
            beta = math.acos(cosValue)
            eta = math.pi - beta
            return -dir.pitch - eta
        else:
            return -dir.pitch

    def getDesiredShotPoint(self):
        scanStart, scanDir = self.__getScanRay()
        if self.__shotPointCalculator is None:
            return self.getThirdPersonShotPoint()
        else:
            return self.__shotPointCalculator.getDesiredShotPoint(scanStart, scanDir)
            return

    def getThirdPersonShotPoint(self):
        if self.__shotPointCalculator is not None:
            return self.__shotPointCalculator.aimPlane.intersectRay(*self.__getScanRay())
        else:
            return AimingSystems.getDesiredShotPoint(*self.__getScanRay())
            return

    def handleMovement(self, dx, dy):
        self.yaw += dx
        self.pitch += dy

    def update(self, deltaTime):
        self.__cursor.update(True)
        aimMatrix = self.__getLookToAimMatrix()
        aimMatrix.postMultiply(self.__cursor.matrix)
        self._matrix.set(aimMatrix)
        if self.__shotPointCalculator is not None:
            self.__shotPointCalculator.update(*self.__getScanRay())
        return 0.0

    def __getScanRay(self):
        scanDir = self.matrix.applyVector(Vector3(0, 0, 1))
        scanStart = self.matrix.translation + scanDir * 0.3
        return (scanStart, scanDir)

    def __getLookToAimMatrix(self):
        return Matrix(self.__aimMatrix)


class _AimPlane(object):
    __EPS_COLLIDE_ARENA = 0.001

    def __init__(self):
        self.__plane = Math.Plane()
        self.init(Vector3(0, 0, 0), Vector3(0, 0, 0))

    def init(self, aimPos, targetPos):
        lookDir = targetPos - aimPos
        self.__lookLength = lookDir.length
        lookDir.normalise()
        self.__plane.init(targetPos, targetPos + Vector3(0, 0, 1), targetPos + Vector3(1, 0, 0))
        self.__initialProjection = Vector3(0, 1, 0).dot(lookDir)

    def intersectRay(self, startPos, dir, checkCloseness = True, checkSign = True):
        collisionPoint = self.__plane.intersectRay(startPos, dir)
        projection = Vector3(0, 1, 0).dot(dir)
        tooClose = collisionPoint.distTo(startPos) - self.__lookLength < -0.0001 and checkCloseness
        parallelToPlane = abs(projection) <= _AimPlane.__EPS_COLLIDE_ARENA
        projectionSignDiffers = projection * self.__initialProjection < 0.0 and checkSign
        backwardCollision = (collisionPoint - startPos).dot(dir) <= 0.0
        if tooClose or parallelToPlane or projectionSignDiffers or backwardCollision:
            return startPos + dir * self.__lookLength
        return collisionPoint


class ShotPointCalculatorPlanar(object):
    MIN_DIST = 50
    TERRAIN_MIN_ANGLE = math.pi / 6
    aimPlane = property(lambda self: self.__aimPlane)

    def __init__(self):
        self.__vehicleMat = BigWorld.player().getOwnVehicleMatrix()
        self.__vehicleDesc = BigWorld.player().vehicleTypeDescriptor
        self.__aimPlane = _AimPlane()
        self.__getTurretMat = functools.partial(AimingSystems.getTurretJointMat, self.__vehicleDesc, self.__vehicleMat)

    def update(self, scanStart, scanDir):
        point, isPointConvenient = self.__testMouseTargetPoint(scanStart, scanDir)
        if isPointConvenient:
            self.__aimPlane.init(scanStart, point)

    def focusAtPos(self, scanStart, scanDir, yawPitch = None):
        scanPos, isPointConvenient = self.__testMouseTargetPoint(scanStart, scanDir)
        if not isPointConvenient:
            if yawPitch is not None:
                turretYaw, gunPitch = yawPitch
                gunMat = AimingSystems.getGunJointMat(self.__vehicleDesc, self.__getTurretMat(turretYaw), gunPitch)
                planePos = self.__aimPlane.intersectRay(gunMat.translation, gunMat.applyVector(Vector3(0, 0, 1)), False, False)
            else:
                planePos = self.__aimPlane.intersectRay(scanStart, scanDir, False)
            if scanStart.distSqrTo(planePos) < scanStart.distSqrTo(scanPos):
                return scanPos
            return planePos
        else:
            self.__aimPlane.init(scanStart, scanPos)
            return scanPos

    def getDesiredShotPoint(self, scanStart, scanDir):
        scanPos, isPointConvenient = self.__testMouseTargetPoint(scanStart, scanDir)
        if isPointConvenient:
            return scanPos
        planePos = self.__aimPlane.intersectRay(scanStart, scanDir)
        if scanStart.distSqrTo(planePos) < scanStart.distSqrTo(scanPos):
            return scanPos
        turretYaw, gunPitch = AimingSystems.getTurretYawGunPitch(self.__vehicleDesc, self.__vehicleMat, planePos, True)
        gunMat = AimingSystems.getGunJointMat(self.__vehicleDesc, self.__getTurretMat(turretYaw), gunPitch)
        aimDir = gunMat.applyVector(Vector3(0, 0, 1))
        return AimingSystems.getDesiredShotPoint(gunMat.translation, aimDir)

    def __calculateClosestPoint(self, start, dir):
        dir.normalise()
        end = start + dir.scale(10000.0)
        testResTerrain = BigWorld.wg_collideSegment(BigWorld.player().spaceID, start, end, 128, lambda matKind, collFlags, itemId, chunkId: collFlags & 8)
        terrainSuitsForCheck = testResTerrain and testResTerrain[1].dot(Math.Vector3(0, 1, 0)) <= math.cos(ShotPointCalculatorPlanar.TERRAIN_MIN_ANGLE)
        testResNonTerrain = BigWorld.wg_collideSegment(BigWorld.player().spaceID, start, end, 136)
        testResDynamic = collideDynamic(start, end, (BigWorld.player().playerVehicleID,), False)
        closestPoint = None
        closestDist = 1000000
        isPointConvenient = True
        if testResTerrain:
            closestPoint = testResTerrain[0]
            closestDist = (testResTerrain[0] - start).length
        if terrainSuitsForCheck:
            isPointConvenient = closestDist >= ShotPointCalculatorPlanar.MIN_DIST
        if testResNonTerrain is not None:
            dist = (testResNonTerrain[0] - start).length
            if dist < closestDist:
                closestPoint = testResNonTerrain[0]
                closestDist = dist
                isPointConvenient = closestDist >= ShotPointCalculatorPlanar.MIN_DIST
        if closestPoint is None and testResDynamic is None:
            return (AimingSystems.shootInSkyPoint(start, dir), True)
        else:
            if testResDynamic is not None:
                dynDist = testResDynamic[0]
                if dynDist <= closestDist:
                    dir = end - start
                    dir.normalise()
                    closestPoint = start + dir * dynDist
                    isPointConvenient = True
            return (closestPoint, isPointConvenient)

    def __testMouseTargetPoint(self, start, dir):
        closestPoint, isPointConvenient = self.__calculateClosestPoint(start, dir)
        turretYaw, gunPitch = AimingSystems.getTurretYawGunPitch(self.__vehicleDesc, self.__vehicleMat, closestPoint, True)
        if not isPointConvenient:
            minPitch, maxPitch = gun_rotation_shared.calcPitchLimitsFromDesc(turretYaw, self.__vehicleDesc.gun['pitchLimits'])
            pitchInBorders = gunPitch <= maxPitch + 0.001
            isPointConvenient = not pitchInBorders
        if isPointConvenient:
            isPointConvenient = not self.__isTurretTurnRequired(dir, turretYaw, closestPoint)
        return (closestPoint, isPointConvenient)

    def __isTurretTurnRequired(self, viewDir, turretYawOnPoint, targetPoint):
        turretMat = self.__getTurretMat(turretYawOnPoint)
        turretPos = turretMat.translation
        gunPos = AimingSystems.getGunJointMat(self.__vehicleDesc, turretMat, 0.0).translation
        dirFromTurretPos = targetPoint - turretPos
        dirFromSniperPos = targetPoint - gunPos
        viewDir = Math.Vector3(viewDir)
        viewDir.y = 0
        viewDir.normalise()
        dirFromSniperPos.y = 0
        dirFromTurretPos.y = 0
        return viewDir.dot(dirFromSniperPos) < 0 or viewDir.dot(dirFromTurretPos) < 0 

 

'SniperAimingSystem.pyc'

import BigWorld
import Math
import GUI
from Math import Vector3, Matrix
import math
from AvatarInputHandler import mathUtils
from AvatarInputHandler import AimingSystems
from AvatarInputHandler.AimingSystems import IAimingSystem
from AvatarInputHandler.Oscillator import Oscillator
from gun_rotation_shared import calcPitchLimitsFromDesc
from projectile_trajectory import getShotAngles

class SniperAimingSystem(IAimingSystem):
    turretYaw = property(lambda self: self.__idealTurretYaw + self.__oscillator.deviation.x)
    gunPitch = property(lambda self: self.__idealGunPitch + self.__oscillator.deviation.y)
    __CONSTRAINTS_MULTIPLIERS = Vector3(1.0, 1.0, 1.0)
    __activeSystem = None

    @staticmethod
    def setStabilizerSettings(useHorizontalStabilizer, useVerticalStabilizer):
        SniperAimingSystem.__CONSTRAINTS_MULTIPLIERS.x = 1.0 if useHorizontalStabilizer else 0.0
        SniperAimingSystem.__CONSTRAINTS_MULTIPLIERS.y = 1.0 if useVerticalStabilizer else 0.0
        if SniperAimingSystem.__activeSystem is not None:
            SniperAimingSystem.__activeSystem.resetIdealDirection()
        return

    @staticmethod
    def getStabilizerSettings():
        return (SniperAimingSystem.__CONSTRAINTS_MULTIPLIERS.x > 0.0, SniperAimingSystem.__CONSTRAINTS_MULTIPLIERS.y > 0.0)

    def __init__(self):
        IAimingSystem.__init__(self)
        self.__idealTurretYaw = 0.0
        self.__idealGunPitch = 0.0
        self.__worldYaw = 0.0
        self.__worldPitch = 0.0
        self.__vehicleTypeDescriptor = None
        self.__vehicleMProv = None
        self.__vehiclePrevMat = None
        self.__yprDeviationConstraints = Vector3(math.pi * 2.1, math.pi / 2 * 0.95, 0.0)
        self.__oscillator = Oscillator(1.0, Vector3(0.0, 0.0, 15.0), Vector3(0.0, 0.0, 3.5), self.__yprDeviationConstraints)
        return

    def destroy(self):
        IAimingSystem.destroy(self)
        SniperAimingSystem.__activeSystem = None
        return

    def enableHorizontalStabilizerRuntime(self, enable):
        yawConstraint = math.pi * 2.1 if enable else 0.0
        self.__yprDeviationConstraints.x = yawConstraint

    def enable(self, targetPos):
        player = BigWorld.player()
        self.__vehicleTypeDescriptor = player.vehicleTypeDescriptor
        self.__vehicleMProv = player.getOwnVehicleMatrix()
        self.__vehiclePrevMat = Matrix(self.__vehicleMProv)
        IAimingSystem.enable(self, targetPos)
        player = BigWorld.player()
        desc = player.vehicleTypeDescriptor
        self.__yawLimits = desc.gun['turretYawLimits']
        self.__idealTurretYaw, self.__idealGunPitch = getShotAngles(desc, player.getOwnVehicleMatrix(), (0, 0), targetPos, False)
        self.__idealTurretYaw, self.__idealGunPitch = self.__clampToLimits(self.__idealTurretYaw, self.__idealGunPitch)
        currentGunMat = AimingSystems.getPlayerGunMat(self.__idealTurretYaw, self.__idealGunPitch)
        self.__worldYaw = currentGunMat.yaw
        self.__worldPitch = (targetPos - currentGunMat.translation).pitch
        self._matrix.set(currentGunMat)
        self.__idealTurretYaw, self.__idealGunPitch = self.__worldYawPitchToTurret(self.__worldYaw, self.__worldPitch)
        self.__idealTurretYaw, self.__idealGunPitch = self.__clampToLimits(self.__idealTurretYaw, self.__idealGunPitch)
        self.__oscillator.reset()
        SniperAimingSystem.__activeSystem = self

    def disable(self):
        SniperAimingSystem.__activeSystem = None
        return

    def getDesiredShotPoint(self):
        start = self.matrix.translation
        scanDir = self.matrix.applyVector(Vector3(0, 0, 1))
        return AimingSystems.getDesiredShotPoint(start, scanDir)

    def resetIdealDirection(self):
        self.__idealTurretYaw, self.__idealGunPitch = self.__worldYawPitchToTurret(self.__worldYaw, self.__worldPitch)
        self.__idealTurretYaw, self.__idealGunPitch = self.__clampToLimits(self.__idealTurretYaw, self.__idealGunPitch)

    def handleMovement(self, dx, dy):
        self.resetIdealDirection()
        self.__idealTurretYaw += dx
        self.__idealGunPitch += dy
        self.__idealTurretYaw, self.__idealGunPitch = self.__clampToLimits(self.__idealTurretYaw, self.__idealGunPitch)
        currentGunMat = AimingSystems.getPlayerGunMat(self.__idealTurretYaw, self.__idealGunPitch)
        self.__worldYaw = currentGunMat.yaw
        self.__worldPitch = currentGunMat.pitch
        self._matrix.set(currentGunMat)
        self.__oscillator.velocity = Vector3(0, 0, 0)

    def __clampToLimits(self, turretYaw, gunPitch):
        if self.__yawLimits is not None:
            turretYaw = mathUtils.clamp(self.__yawLimits[0], self.__yawLimits[1], turretYaw)
        desc = BigWorld.player().vehicleTypeDescriptor
        pitchLimits = calcPitchLimitsFromDesc(turretYaw, desc.gun['pitchLimits'])
        pitchLimitsMin = pitchLimits[0]
        pitchLimitsMax = pitchLimits[1]
        gunPitch = mathUtils.clamp(pitchLimitsMin, pitchLimitsMax, gunPitch)
        return (turretYaw, gunPitch)

    def __worldYawPitchToTurret(self, worldYaw, worldPitch):
        worldToTurret = Matrix(self.__vehicleMProv)
        worldToTurret.invert()
        worldToTurret.preMultiply(mathUtils.createRotationMatrix((worldYaw, worldPitch, 0)))
        return (worldToTurret.yaw, worldToTurret.pitch)

    def update(self, deltaTime):
        self.__oscillator.constraints = mathUtils.matrixScale(self.__yprDeviationConstraints, SniperAimingSystem.__CONSTRAINTS_MULTIPLIERS)
        vehicleMat = Matrix(self.__vehicleMProv)
        curTurretYaw, curGunPitch = self.__worldYawPitchToTurret(self.__worldYaw, self.__worldPitch)
        yprDelta = Vector3(curTurretYaw - self.__idealTurretYaw, curGunPitch - self.__idealGunPitch, 0)
        self.__oscillator.deviation = yprDelta
        self.__oscillator.update(deltaTime)
        curTurretYaw = self.__idealTurretYaw + self.__oscillator.deviation.x
        curGunPitch = self.__idealGunPitch + self.__oscillator.deviation.y
        curTurretYaw, curGunPitch = self.__clampToLimits(curTurretYaw, curGunPitch)
        yprDelta = Vector3(curTurretYaw - self.__idealTurretYaw, curGunPitch - self.__idealGunPitch, 0)
        self.__oscillator.deviation = yprDelta
        currentGunMat = AimingSystems.getPlayerGunMat(curTurretYaw, curGunPitch)
        self.__worldYaw = currentGunMat.yaw
        self.__worldPitch = currentGunMat.pitch
        self._matrix.set(currentGunMat)
        self.__vehiclePrevMat = vehicleMat
        return 0.0 

 

'StrategicAimingSystem.pyc'

import BigWorld
import Math
from Math import Vector3, Matrix
import math
from AvatarInputHandler import mathUtils, AimingSystems
from AvatarInputHandler.AimingSystems import IAimingSystem
from AvatarInputHandler.cameras import _clampPoint2DInBox2D

class StrategicAimingSystem(IAimingSystem):
    _LOOK_DIR = Vector3(0, -math.cos(0.001), math.sin(0.001))
    height = property(lambda self: self.__height)

    def __init__(self, height, yaw):
        self._matrix = mathUtils.createRotationMatrix((yaw, 0, 0))
        self.__planePosition = Vector3(0, 0, 0)
        self.__height = height

    def destroy(self):
        pass

    def enable(self, targetPos):
        self.updateTargetPos(targetPos)

    def disable(self):
        pass

    def getDesiredShotPoint(self):
        return AimingSystems.getDesiredShotPoint(self._matrix.translation, Vector3(0, -1, 0), True, True)

    def handleMovement(self, dx, dy):
        shift = self._matrix.applyVector(Vector3(dx, 0, dy))
        self.__planePosition += Vector3(shift.x, 0, shift.z)
        self.__updateMatrix()

    def updateTargetPos(self, targetPos):
        self.__planePosition.x = targetPos.x
        self.__planePosition.z = targetPos.z
        self.__updateMatrix()

    def __updateMatrix(self):
        bb = BigWorld.player().arena.arenaType.boundingBox
        pos2D = _clampPoint2DInBox2D(bb[0], bb[1], Math.Vector2(self.__planePosition.x, self.__planePosition.z))
        self.__planePosition.x = pos2D[0]
        self.__planePosition.z = pos2D[1]
        collPoint = BigWorld.wg_collideSegment(BigWorld.player().spaceID, self.__planePosition + Math.Vector3(0, 1000.0, 0), self.__planePosition + Math.Vector3(0, -250.0, 0), 3)
        heightFromPlane = 0.0 if collPoint is None else collPoint[0][1]
        self._matrix.translation = self.__planePosition + Vector3(0, heightFromPlane + self.__height, 0)
        return 

Share this post


Link to post

Short link
Share on other sites

Не-не-не, мне не нужна картинка :) Нужно поведение прицела, как для консольных игр. Я наверное не совсем внятно описал что к чему.

 

Есть так называемый круг сведения, т.е. случайным образом снаряд летит в любую точку внутри этого круга.

Есть так называемый прицел, который по сути является точкой по середине экрана.

Существуют формулы полета снаряда, и если прицел наведен на танк и танк подсвечен - в формулу добавляется расстояние до цели.

 

Необходимо каким-то образом подсвечивать танк, когда он находиться в кругу сведения, ведь тогда будет в формуле учитываться расстояние до этого танка и с большей вероятностью снаряд влетит в танк (чем если целиться рядом с противником, особенно когда он не подсвечен).

 

Учитывая клиент-серверную архитектуру игры, наверное это невозможно, но я - я ж просто спрашиваю.

Есть похожий мод(фиксация прицела).Наводишь на положение танка противника, зажимаешь кнопку и прицел наводится на то место с пересчитыванием траектории.Особенно помогает таким танкам как Е100 или 268 с "фугасной" траекторией.Правда не знаю, был ли апдейт под текущий патч, но в теме можете узнать.

Есть еще нечто подобное(помимо автоприцела), но работа мода отличается, не вникал глубоко,но работа мода отличается,не вникал глубоко.

  • Upvote 1

Share this post


Link to post

Short link
Share on other sites

Есть похожий мод(фиксация прицела).Наводишь на положение танка противника, зажимаешь кнопку и прицел наводится на то место с пересчитыванием траектории.Особенно помогает таким танкам как Е100 или 268 с "фугасной" траекторией.Правда не знаю, был ли апдейт под текущий патч, но в теме можете узнать.

Есть еще нечто подобное(помимо автоприцела), но работа мода отличается, не вникал глубоко,но работа мода отличается,не вникал глубоко.

Ушёл курить темы, спасибо!

P.S. За авторога отдельное спасибо! Вручную влом постоянно переставлять, а тут такой подарок. Правильный расчёт баллистики и расширенный автоприцел в принципе тоже "маст хэв".

Share this post


Link to post

Short link
Share on other sites

Ушёл курить темы, спасибо!

P.S. За авторога отдельное спасибо! Вручную влом постоянно переставлять, а тут такой подарок. Правильный расчёт баллистики и расширенный автоприцел в принципе тоже "маст хэв".

Да,крайне удобный мод,уже несколько патчей юзаю))

Share this post


Link to post

Short link
Share on other sites

Написал создателю "Вычислителю Баллистического Мода" просьбу о предоставлении исходников для ковыряний. Думаю не даст, но натолкнул на мысль что мне подойдет замена луча в прицеле на угол. Может есть у кого исходники мода лазерного прицела? Думаю стоит поковырять их...

Share this post


Link to post

Short link
Share on other sites

Написал создателю "Вычислителю Баллистического Мода" просьбу о предоставлении исходников для ковыряний. Думаю не даст, но натолкнул на мысль что мне подойдет замена луча в прицеле на угол. Может есть у кого исходники мода лазерного прицела? Думаю стоит поковырять их...

 

Скинул тебе исходники БалВыча в личку.

  • Upvote 1

Share this post


Link to post

Short link
Share on other sites

Скинул тебе исходники БалВыча в личку.

Спасибо тебе, добрый человек!!!

С разрешения уважаемого StranikS_Scan, выкладываю нашу личную переписку для понимания общей картины для жителей форума:

Доброе время суток, изучаю тему относительно модернизации прицела. Как я понимаю в игре точка, являющаяся видимым прицелом, есть некий луч, который в Вашем моде сделали видимым.

Интересует следующее - Ваше мнение каково, можно ли поменять луч (прицел) на телесный угол, скажем в 1 градус?

 

Про порыться в исходниках и не спрашиваю...

Ээээ, в моём это каком моде? Вы про лазеры? Тогда я скажу что ни какого отношения лазеры не имеют к прицелу и механизму прицеливания вообще. Лазер это модель в виде тонкого цветного цилиндра, которая добавляется в игру и жестко скрепляется с моделью пушки, в результате этот лазер перемещается вместе с пушкой.

 

Почитал тему:

 

1. Вы правы в игре есть условный "дальномер", который показывает расстояние между центром вашего танка (обычно точка на вертикальной оси вращения башни, лежащая на уровне земли) и точкой куда показывает центр вашего прицела. Обратите внимание что именно вашего прицела, а не серверного.

 

2. Del

3. "В случае пятна прицела (не точки) танк будет подсвечиваться даже когда край пятна попадет на контуры" - да в принципе такое можно сделать, если проверять наличие танка в определенном радиусе от точки прицеливания

 

4. "соответственно формула полета снаряда применяется" - в формуле расчета выстрела фигурирует только дальность измеряемая дальномером из п.1. и эа цифра передается на сервер после чего сервер делает расчет траектории и сам выстрел. Если у вас вместо точки пятно - то какую цифру вы будете передавать серверу как дальность??? Передать можно только одну цифру, одна цифра соот. одной точке, а у вас область будет а не точка - так какую цифру передавать?

 

5. Судя по тому что вы пишите в теме. В вашем случае надо из всех точек области найти точку с минимальным расстояние и именно эту цифру и выдать как результат работы дальномера. Тогда да, если в моем пятне будет небо и кусочек танка, то дальномер вернет в качестве дальности расстояние до танка а не "неба"

 

6. Что касается реализации, то нужно написать алгоритм, который анализирует расстояние до n-точек в пределах r-радиуса (или на самой окружности r-радиуса, смотря как делать) от центра прицела. Думаю если n будет много, то будут жуткие тормоза, а если n будет мало, то мелкие краешки попадающие на границу такого пятна могут быть и не проанализированы.

 

7. Я на оф. форуме вроде выдел аналог БалВыча, в котором не нужно нажимать кнопку для фиксации расстояния, там какой алгоритм есть более хитрый, который не дает скакать дальномеру. Но думаю там просто таймер есть на время действия которого запоминается предыдущее значение дальномера при больших разностях в его показаниях. Поищите этот мод.

1. Значит не даром мое гугление прошло.

2. Спасибо! Буду курить скрипт.

Небольшое отступление перед следующими пунктами. Более детальное взвешивание всех составляющих приводит к мысли 6-ти гранного конуса (сота в основании). Формула проста и подходит под параметры.

3. Проверять наличие танка в 7 точках (шестигранник или сота и центр).

4. Передавать точку из шестигранника, если более 2 одновременно наведены на цель, то среднее значение.

5. Оффтоп - фугасами будет интересно стрелять - можно и мод обозвать как фугасный прицел ;)

6. Вот это и хочу подсмотреть в скрипте (как вы выразились) БалВыча, а рассчитываться в игре будет то только одна точка, просто 7 будет проверяться.

7. Поищу, спасибо за подсказку.

Я так понимаю, что цифра от центра соты "будет поступать" как базовая дальность, после чего будет проверка наличия моделей танков в 6 точках соты и если одна из них сработает, то дальность с нее будет использована вместо базовой, если сработает больше 1 вершины, то будет браться среднее/мин/макс... значение из их дальностей. Если ни одна вершина не сработает, то дальность останется базовой.

 

В такой логике вроде нет изъянов. Качество работы будет зависеть от размеры соты и от критерия расчета дальности при "срабатывании" больше 1 вершины.

Размер соты будет неплохо сделать динамическим.

Соответственно надо отталкиваться от угла а не от размера соты, 1 или 2 градуса, методом проб можно подобрать, как и формулу расчета по вершинам.

Я понимаю о каком конусе идёт речь, но если угол вращения константа, а мы видим только соту в основании 6-гранной пирамиды, то размер этой соты будет зависеть от расстояния от нас до базовой точки, значит по принципу перспективы будет так, когда я прицеливаюсь в даль размер соты будет большой, а когда смотрю на близкостоящий объект - то сота будет очень маленькой.... зачем такое нужно?

 

мммм или нет, будет константа из-за перспективы?

 

Не проще ли сначала сделать соту статического размера на экране прицела и глянуть что это даст?

Если бы знать ещё как её делать ;) Я пока только в теории разбираюсь. Согласен, что сделать сотовый прицел статикой - это начало, но правильное понимание всей картины в целом тоже нужно, мое мнение имхо. Хотя иногда бывает, что лучше делать правильно изначально пусть и более трудоемко, как гласит пословица - "нет ничего более постоянного, чем временное".

 

Разумеется что такой прицел будет сугубо аркадным (снайперский нужно оставить как есть), например для максимальной дальности обнаружения противника в 445 метров диаметр соты для конуса в 1о составит чуть менее 8 метров, но даст преимущество в захвате врага в автоприцел на высокой скорости, а так же будет правильные значения отправлять в игру при выстреле. Так что ХЗ как будет правильно.

 

Буду курить скрипты и python.

 

Хочу спросить разрешение выложить нашу переписку в темку.

Да выложи, а то там не поняли что ты хочешь сделать

Edited by kharlashkin

Share this post


Link to post

Short link
Share on other sites

@StranikS_Scan, @kharlashkin, прошу помощи!

С каждым новым обновлением AvatarInputHandler нуждается в переделке. Я понятия не имею, где и как... Постоянно приходится выковыривать из чужих модпаков, а т.к. в последнее время многие устремились  к ПМОДу (который мне не нравится), вообще не могу найти AvatarInputHandler. 

Помогите, пожалуйста, если это не сложно, объясните, что именно меняется от версии к версии. Ну или просто (если есть конечно) залейте AvatarInputHandler для 0.9.2.

Заранее благодарен!

Share this post


Link to post

Short link
Share on other sites

@StranikS_Scan, @kharlashkin, прошу помощи!

С каждым новым обновлением AvatarInputHandler нуждается в переделке. Я понятия не имею, где и как... Постоянно приходится выковыривать из чужих модпаков, а т.к. в последнее время многие устремились  к ПМОДу (который мне не нравится), вообще не могу найти AvatarInputHandler. 

Помогите, пожалуйста, если это не сложно, объясните, что именно меняется от версии к версии. Ну или просто (если есть конечно) залейте AvatarInputHandler для 0.9.2.

Заранее благодарен!

Вообще непонятно... 

AvatarInputHandler - это "картохины" скрипты, для 0.9.2 я не качал тестовый клиент, но и не факт что те скрипты попадут в "продакшн".

Если имеются ввиду какие-то модифицированные скрипты, то лучше наверное у создателей модов поспрашивать.

Share this post


Link to post

Short link
Share on other sites

У меня 0.9.2 нет, но могу написать как научиться делать такой мод на примере клиента 0.9.1.

 

1. AvatarInputHandler.xml орыыыгинальный хранится усегда в:

c:\Games\World_of_Tanks\res\packages\gui.pkg\\gui\avatar_input_handler.xml

Извлюкать мона любым архиватором так как это по сути zip-архив

 

2. Теперь его надо перекодировать из сжатого формата в обычный текстовый

- берем идем в эту тему и качаем вот ету программу WotModTools

- запускаем, пететаскиваем туда наш xml, видим читабельный текст, сохраняем его в тот же файл

- открываем файл любым тектовым редактором и через Замена - Заменить всё, заменяем все запятые в тексте на точки

В итоге получаем читабельную рабочую версию этого файла для 0.9.1.

 

3. Берем старый модифицированный файл avatar_input_handler.xml из темы скажем Старый серверный прицел 0.9.1 или из темы PMOD c баранками 0.9.1, открываем TotalCommander, выделяем наш новый avatar_input_handler.xml полученный в п.2. и старый модифицированный avatar_input_handler.xml, после чего жмякаем в главном меню - Сравнить файлы по содержимому.

 

Далее сидим, курим и сравниваем в чем разница. Эта разница и есть - то что мододелы в нем изменили. Изучаем и запоминаем.

 

4. Теперь качаем 0.9.2 и делаем такой файлик уже самостоятельно....

 

5. Не забываем что в папке res_mods чтобы этот файлик работал его класть надо вот так:

c:\Games\World_of_Tanks\res_mods\0.9.1\gui\avatar_input_handler.xml

Edited by StranikS_Scan
  • Upvote 4

Share this post


Link to post

Short link
Share on other sites

@StranikS_Scan, спасибо!
файлы полученные в результате п.2 в 0.9.1 и 0.9.2_СТ - идентичны (запятых, кстати, не было изначально) .

поместив этот файлик по указанному пути, результат тот же: в бой не заходит. не пускает папка  AvatarInputHandler из (res_mods\0.9.2 Common Test\scripts\client)

в которой aims.pyc и папка  DynamicCameras с ArcadeCamera.pyc, SniperCamera.pyc и StrategicCamera.pyc.

ЗЫ. может быть вы знаете автора мода, обращусь к нему.

Share this post


Link to post

Short link
Share on other sites

 

 

 ArcadeCamera.pyc, SniperCamera.pyc и StrategicCamera.pyc.

 

А вот про эти файлики я ни чего не писал выше. Именно эти файлики и не работают с 0.9.1 на 0.9.2, их авторы постарались чтоб они не робили :)))) 

Share this post


Link to post

Short link
Share on other sites

 я предположил, что т.к они находятся в папке AvatarInputHandler, то вы про них тоже что нибудь расскажете!

но видать придется дальше "бороздить просторы", "в поисках утраченного" )))

Share this post


Link to post

Short link
Share on other sites

 я предположил, что т.к они находятся в папке AvatarInputHandler, то вы про них тоже что нибудь расскажете!

но видать придется дальше "бороздить просторы", "в поисках утраченного" )))

 

Там шифрование стоит, вскрыть их не удастся. Попробуйте через авторов. Но они скорее всего напишу, ждите выхода патча, мы сами обновим, вы скачаете. Как-то так.

  • Upvote 1

Share this post


Link to post

Short link
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...