ziggi / FCNPC

FCNPC - Fully Controllable NPC
Apache License 2.0
139 stars 31 forks source link

Correct Delta Calculations #299

Open Pottus opened 1 year ago

Pottus commented 1 year ago

This was always one thing I wanted with FCNPC was delta playback since it was not supported correctly. I am just pasting my code snippet for the solution to this problem and perhaps someone could do an official implementation with some tweaks.

It takes 3 parameters

Position to start playback const CVector& vecPoint

float* fQuaternion Passed from the script with but there is a probably a better way to reference this FCNPC_GetQuaternion(npcid, rw, rx, ry, rz);

Lets you specify rotation offset angle for play back float zoff

Some more notes: Recordings should be made at 0, 0, 0 you could do say a series of attack punches then play that back anywhere at any angle, other use is recording jumping down off a ledge.

`bool CPlayback::Initialize(const CVector& vecPoint, float* fQuaternion, float zoff) { if (m_iRecordId == INVALID_RECORD_ID) { return false; }

m_recordData = pServer->GetRecordManager()->Get(m_iRecordId);

if (vecPoint != CVector()) {
    int iSize = static_cast<int>(m_recordData.v_dwTime.size());

    if (m_recordData.iPlaybackType == PLAYBACK_TYPE_DRIVER) {
        CVector vecPointOffset = m_recordData.v_vehicleSyncData[0].vecPosition - vecPoint;

        for (int i = 0; i < iSize; i++) {
            m_recordData.v_vehicleSyncData[i].vecPosition -= vecPointOffset;
        }
    }

    else if (m_recordData.iPlaybackType == PLAYBACK_TYPE_ONFOOT) {

        CVector vecPointOffset = m_recordData.v_playerSyncData[0].vecPosition - vecPoint;
        CVector Initial = m_recordData.v_playerSyncData[0].vecPosition - vecPointOffset;

        float s, c;

        s = sin(zoff * M_PI / 180);
        c = cos(zoff * M_PI / 180);

        btQuaternion deltaRot;
        btQuaternion currentRot;

        deltaRot.setW(fQuaternion[0]);
        deltaRot.setX(fQuaternion[1]);
        deltaRot.setY(fQuaternion[2]);
        deltaRot.setZ(fQuaternion[3]);

        currentRot += deltaRot;

        for (int i = 0; i < iSize; i++) {

            if (zoff < 0.0 || zoff > 0.0)
            {
                m_recordData.v_playerSyncData[i].byteHealth = 255;
                m_recordData.v_playerSyncData[i].byteArmour = 255;

                // Perform position calculations
                float xNew, yNew;

                xNew = (m_recordData.v_playerSyncData[i].vecPosition.fX * c - m_recordData.v_playerSyncData[i].vecPosition.fY * s);
                yNew = (m_recordData.v_playerSyncData[i].vecPosition.fX * s + m_recordData.v_playerSyncData[i].vecPosition.fY * c);

                m_recordData.v_playerSyncData[i].vecPosition.fX = xNew + Initial.fX;
                m_recordData.v_playerSyncData[i].vecPosition.fY = yNew + Initial.fY;
                m_recordData.v_playerSyncData[i].vecPosition.fZ -= vecPointOffset.fZ;

                // Perform rotation calculations
                currentRot.setW(m_recordData.v_playerSyncData[i].fQuaternion[0]);
                currentRot.setX(m_recordData.v_playerSyncData[i].fQuaternion[1]);
                currentRot.setY(m_recordData.v_playerSyncData[i].fQuaternion[2]);
                currentRot.setZ(m_recordData.v_playerSyncData[i].fQuaternion[3]);

                if (fQuaternion) {
                    currentRot *= deltaRot;
                    m_recordData.v_playerSyncData[i].fQuaternion[0] = currentRot.getW();
                    m_recordData.v_playerSyncData[i].fQuaternion[1] = currentRot.getX();
                    m_recordData.v_playerSyncData[i].fQuaternion[2] = currentRot.getY();
                    m_recordData.v_playerSyncData[i].fQuaternion[3] = currentRot.getZ();
                }

                // Perform velocity calculations

                btQuaternion currentVelocity;

                currentVelocity.setW(0.0);
                currentVelocity.setX(m_recordData.v_playerSyncData[i].vecVelocity.fX);
                currentVelocity.setY(m_recordData.v_playerSyncData[i].vecVelocity.fY);
                currentVelocity.setZ(m_recordData.v_playerSyncData[i].vecVelocity.fZ);

                btQuaternion rotateVelocity;
                rotateVelocity.setW(1 / zoff);
                rotateVelocity.setX(0.0);
                rotateVelocity.setY(0.0);
                rotateVelocity.setZ(0.0);

                currentVelocity *= rotateVelocity;

                m_recordData.v_playerSyncData[i].vecVelocity.fX = currentVelocity.getX();
                m_recordData.v_playerSyncData[i].vecVelocity.fY = currentVelocity.getY();
                m_recordData.v_playerSyncData[i].vecVelocity.fZ = currentVelocity.getZ();

            }
            else
                m_recordData.v_playerSyncData[i].vecPosition -= vecPointOffset;
        }
    }
}

m_dwStartTime = GetTickCount();
return true;

}`