Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
898 lines
24 KiB
C++
898 lines
24 KiB
C++
//===========================================================================//
|
|
// File: MissionReview.cpp
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 07/11/2000 JSE Inital coding
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 2000, Microsoft Corp. //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
|
|
#include "MW4Headers.hpp"
|
|
#include "MissionReview.hpp"
|
|
#include "MWMission.hpp"
|
|
#include "MWApplication.hpp"
|
|
#include "MWPlayer.hpp"
|
|
#include "Bucket.hpp"
|
|
#include <Adept\DamageObject.hpp>
|
|
#include <Adept\Map.hpp>
|
|
|
|
#if !defined(NO_MR)
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
MRPlayerData::MRPlayerData()
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void MRPlayerData::Reset()
|
|
{
|
|
m_playerStatus = NoChange;
|
|
m_playerName = NULL;
|
|
m_position = Point3D::Identity;
|
|
m_yawRotation = 0.0f;
|
|
m_takenDamage = false;
|
|
m_firedWeapon = false;
|
|
m_alive = false;
|
|
|
|
|
|
m_scoreBucket1 = 0;
|
|
m_scoreBucket2 = 0;
|
|
m_scoreBucket3 = 0;
|
|
|
|
|
|
for (int i = 0; i < Damage_Zones; ++i)
|
|
{
|
|
m_damageLevel[i] = 0;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
MissionReview::MissionReview():
|
|
Plug(DefaultData)
|
|
{
|
|
|
|
m_missionLog = NULL;
|
|
m_nameLog = NULL;
|
|
|
|
for (int i = 0; i < Maximum_Players; ++i)
|
|
{
|
|
m_playBackLog[i] = NULL;
|
|
}
|
|
|
|
ClearLog();
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
MissionReview::~MissionReview()
|
|
{
|
|
|
|
ClearLog();
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void MissionReview::ClearLog(void)
|
|
{
|
|
timeSinceLastSnapShot = 0.0;
|
|
m_playersInGame = 0;
|
|
m_bufferedSnapShots = 0;
|
|
m_totalSnapShots = 0;
|
|
m_snapShotFrequency = 0.0f;
|
|
for (int i = 0; i < Maximum_Players; ++i)
|
|
{
|
|
m_playerData[i].Reset();
|
|
|
|
if (m_playBackLog[i] != NULL)
|
|
{
|
|
delete[] m_playBackLog[i];
|
|
m_playBackLog[i] = NULL;
|
|
}
|
|
}
|
|
|
|
if (m_missionLog != NULL)
|
|
{
|
|
delete m_missionLog;
|
|
m_missionLog = NULL;
|
|
}
|
|
|
|
if (m_nameLog != NULL)
|
|
{
|
|
delete m_nameLog;
|
|
m_nameLog = NULL;
|
|
}
|
|
|
|
minExtents = Point3D::Identity;
|
|
maxExtents = Point3D::Identity;
|
|
missionName = "\0";
|
|
|
|
haveHeaderInfo = false;
|
|
|
|
m_mode = NoMode;
|
|
m_recording = false;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void MissionReview::ReadyRecord()
|
|
{
|
|
ClearLog();
|
|
m_mode = RecordMode;
|
|
|
|
m_missionLog = new DynamicMemoryStream;
|
|
m_missionLog->AllocateBytes(1000000); // about one meg
|
|
m_nameLog = new DynamicMemoryStream;
|
|
m_nameLog->AllocateBytes(64000); // alot of friggin names...
|
|
}
|
|
|
|
|
|
|
|
void MissionReview::StartRecordingLog(Scalar frequency)
|
|
{
|
|
|
|
m_recording = true;
|
|
|
|
m_snapShotFrequency = frequency;
|
|
|
|
Mission *miss = Mission::GetInstance();
|
|
Check_Object(miss);
|
|
missionName = miss->GetModelName ();
|
|
|
|
Map::GetInstance()->GetMapExtents(&minExtents.z, &maxExtents.z, &minExtents.x, &maxExtents.z);
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void MissionReview::StopRecordingLog(void)
|
|
{
|
|
Verify(m_mode == RecordMode);
|
|
|
|
m_nameLog->WriteByteAlign();
|
|
m_missionLog->WriteByteAlign();
|
|
|
|
m_nameLog->Rewind();
|
|
m_missionLog->Rewind();
|
|
|
|
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void MissionReview::AddPlayer(const char *player_name, int id)
|
|
{
|
|
Verify(m_mode == RecordMode);
|
|
|
|
int token = AddToken;
|
|
m_nameLog->WriteBytes(&token, 1);
|
|
m_nameLog->WriteBytes(&m_bufferedSnapShots, 4);
|
|
m_nameLog->WriteBytes(&id, 1);
|
|
|
|
int size = strlen(player_name);
|
|
size++;
|
|
m_nameLog->WriteBytes(&size, 1);
|
|
m_nameLog->WriteBytes(player_name, size);
|
|
|
|
m_playerData[id].Reset();
|
|
m_playerData[id].m_playerName = player_name;
|
|
m_playerData[id].m_playerStatus = MRPlayerData::InToken;
|
|
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void MissionReview::RemovePlayer(int id)
|
|
{
|
|
Verify(m_mode == RecordMode);
|
|
|
|
int token = RemoveToken;
|
|
m_nameLog->WriteBytes(&token, 1);
|
|
m_nameLog->WriteBytes(&m_bufferedSnapShots, 4);
|
|
m_nameLog->WriteBytes(&id, 1);
|
|
|
|
m_playerData[id].Reset();
|
|
|
|
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void MissionReview::TakeSnapShot()
|
|
{
|
|
Verify(m_mode == RecordMode);
|
|
|
|
if (!m_recording)
|
|
return;
|
|
|
|
if ((gos_GetElapsedTime() - timeSinceLastSnapShot) < m_snapShotFrequency)
|
|
{
|
|
return;
|
|
}
|
|
|
|
timeSinceLastSnapShot = gos_GetElapsedTime();
|
|
++m_bufferedSnapShots;
|
|
m_totalSnapShots = m_bufferedSnapShots;
|
|
|
|
MWMission *mission = Cast_Object(MWMission*, Mission::GetInstance());
|
|
for (int i = 0; i < Maximum_Players; ++i)
|
|
{
|
|
if (m_playerData[i].m_playerStatus == MRPlayerData::InToken)
|
|
{
|
|
MWApplication *app = MWApplication::GetInstance();
|
|
Verify(app->servedConnectionData[i].clientConnected);
|
|
Verify(app->servedConnectionData[i].clientPlayer != NULL);
|
|
Verify(app->servedConnectionData[i].clientPlayer->vehicle != NULL);
|
|
|
|
m_playerData[i].m_alive = (app->servedConnectionData[i].clientPlayer->vehicle->executionState->GetState() != Entity::ExecutionStateEngine::NeverExecuteState)?1:0;
|
|
|
|
|
|
m_playerData[i].m_position = app->servedConnectionData[i].clientPlayer->vehicle->GetLocalToWorld();
|
|
YawPitchRange ypr;
|
|
|
|
|
|
if (app->servedConnectionData[i].clientPlayer->vehicle->GetClassID() == MechClassID)
|
|
{
|
|
Mech *mech = Cast_Object(Mech*,app->servedConnectionData[i].clientPlayer->vehicle);
|
|
|
|
Stuff::UnitVector3D vector;
|
|
mech->animationArray[mech->torsoAboveJointIndex]->GetLocalToWorld().GetLocalForwardInWorld(&vector);
|
|
|
|
ypr = vector;
|
|
|
|
//ypr = app->servedConnectionData[i].clientPlayer->vehicle->GetLocalToWorld();
|
|
m_playerData[i].m_yawRotation = ypr.yaw;
|
|
}
|
|
else
|
|
{
|
|
|
|
Stuff::UnitVector3D vector;
|
|
app->servedConnectionData[i].clientPlayer->vehicle->GetLocalToWorld().GetLocalForwardInWorld(&vector);
|
|
|
|
ypr = vector;
|
|
|
|
m_playerData[i].m_yawRotation = ypr.yaw;
|
|
}
|
|
|
|
|
|
CBucket *bucket = mission->m_BucketManager->PlayerBucket( app->servedConnectionData[i].clientPlayer->vehicle->GetReplicatorID(), CBucketManager::CUSTOM);
|
|
if (bucket)
|
|
m_playerData[i].m_scoreBucket1 = bucket->Value();
|
|
else
|
|
m_playerData[i].m_scoreBucket1 = 0;
|
|
|
|
bucket = mission->m_BucketManager->PlayerBucket( app->servedConnectionData[i].clientPlayer->vehicle->GetReplicatorID(), CBucketManager::KILLS);
|
|
if (bucket)
|
|
m_playerData[i].m_scoreBucket2 = bucket->Value();
|
|
else
|
|
m_playerData[i].m_scoreBucket2 = 0;
|
|
|
|
bucket = mission->m_BucketManager->PlayerBucket( app->servedConnectionData[i].clientPlayer->vehicle->GetReplicatorID(), CBucketManager::DEATHS);
|
|
if (bucket)
|
|
m_playerData[i].m_scoreBucket3 = bucket->Value();
|
|
else
|
|
m_playerData[i].m_scoreBucket3 = 0;
|
|
|
|
|
|
// weapon and damage bools are pre fed...
|
|
|
|
// read damage state...
|
|
|
|
int current_damage_object = 0;
|
|
|
|
|
|
if (app->servedConnectionData[i].clientPlayer->vehicle->IsDestroyed())
|
|
{
|
|
m_playerData[i].m_damageLevel[current_damage_object] = 1.0f;
|
|
}
|
|
else
|
|
{
|
|
m_playerData[i].m_damageLevel[current_damage_object] = 0.0f;
|
|
}
|
|
|
|
++current_damage_object;
|
|
|
|
|
|
DamageObject *damage_object;
|
|
Vehicle *vehicle = app->servedConnectionData[i].clientPlayer->GetVehicle();
|
|
SortedChainIteratorOf<DamageObject *, int> damage_iterator(&vehicle->damageObjects);
|
|
|
|
while((damage_object = damage_iterator.ReadAndNext()) != NULL)
|
|
{
|
|
Verify(current_damage_object < MRPlayerData::Damage_Zones);
|
|
Check_Object(damage_object);
|
|
m_playerData[i].m_damageLevel[current_damage_object] = damage_object->GetHighResDamageLevel();
|
|
++current_damage_object;
|
|
}
|
|
|
|
// write the player into the log...
|
|
|
|
Scalar min_z, max_z, min_x, max_x;
|
|
Map::GetInstance()->GetMapExtents(&min_z, &max_z, &min_x, &max_x);
|
|
|
|
m_missionLog->WriteScaledFloatToBits(m_playerData[i].m_position.x, min_x, max_x, XBitDepth);
|
|
m_missionLog->WriteScaledFloatToBits(m_playerData[i].m_position.z, min_z, max_z, YBitDepth);
|
|
m_missionLog->WriteScaledFloatToBits(m_playerData[i].m_yawRotation, -Stuff::Pi, Stuff::Pi, RotationBitDepth);
|
|
m_missionLog->WriteBits(&m_playerData[i].m_scoreBucket1, 32);
|
|
m_missionLog->WriteBits(&m_playerData[i].m_scoreBucket2, 32);
|
|
m_missionLog->WriteBits(&m_playerData[i].m_scoreBucket3, 32);
|
|
|
|
m_missionLog->WriteBit(m_playerData[i].m_takenDamage);
|
|
m_missionLog->WriteBit(m_playerData[i].m_firedWeapon);
|
|
m_missionLog->WriteBit(m_playerData[i].m_alive);
|
|
m_playerData[i].m_takenDamage = false;
|
|
m_playerData[i].m_firedWeapon = false;
|
|
|
|
for (int dz = 0; dz < MRPlayerData::Damage_Zones; ++dz)
|
|
{
|
|
m_missionLog->WriteScaledFloatToBits(m_playerData[i].m_damageLevel[dz], 0.0f, 1.0f, DamageBitDepth);
|
|
}
|
|
|
|
m_missionLog->WriteByteAlign();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void MissionReview::SaveLog(const char *file_name)
|
|
{
|
|
Verify(m_mode == RecordMode);
|
|
|
|
Stuff::FileStream file_stream(file_name, Stuff::FileStream::WriteOnly);
|
|
|
|
DWORD token = 0xAAAAAAAA;
|
|
file_stream.WriteBytes(&token, 4);
|
|
file_stream << missionName;
|
|
file_stream << minExtents << maxExtents;
|
|
|
|
file_stream.WriteBytes(&m_totalSnapShots, 4);
|
|
file_stream.WriteBytes(&m_snapShotFrequency, 4);
|
|
int size = m_nameLog->GetBufferBytesUsed();
|
|
file_stream.WriteBytes(&size, 4);
|
|
if (size > 0)
|
|
{
|
|
file_stream.WriteBytes(m_nameLog->GetPointer(), m_nameLog->GetBufferBytesUsed());
|
|
}
|
|
size = m_missionLog->GetBufferBytesUsed();
|
|
file_stream.WriteBytes(&size, 4);
|
|
if (size > 0)
|
|
{
|
|
file_stream.WriteBytes(m_missionLog->GetPointer(), m_missionLog->GetBufferBytesUsed());
|
|
}
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void MissionReview::GetHeader(DynamicMemoryStream *stream)
|
|
{
|
|
|
|
DWORD token = 0xAAAAAAAA;
|
|
stream->WriteBytes(&token, 4);
|
|
*stream << missionName;
|
|
*stream << minExtents << maxExtents;
|
|
stream->WriteBytes(&m_totalSnapShots, 4);
|
|
stream->WriteBytes(&m_snapShotFrequency, 4);
|
|
int size = m_nameLog->GetBufferBytesUsed();
|
|
stream->WriteBytes(&size, 4);
|
|
if (size > 0)
|
|
{
|
|
stream->WriteBytes(m_nameLog->GetPointer(), m_nameLog->GetBufferBytesUsed());
|
|
}
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void MissionReview::GetDataLog(DynamicMemoryStream *stream)
|
|
{
|
|
m_missionLog->Rewind();
|
|
int size = m_missionLog->GetBufferBytesUsed();
|
|
stream->WriteBytes(&size, 4);
|
|
if (size > 0)
|
|
{
|
|
stream->WriteBytes(m_missionLog->GetPointer(), m_missionLog->GetBufferBytesUsed());
|
|
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
bool MissionReview::HaveLog(void)
|
|
{
|
|
return haveHeaderInfo;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void MissionReview::StartLogBuffer(void)
|
|
{
|
|
ClearLog();
|
|
m_missionLog = new DynamicMemoryStream;
|
|
m_nameLog = new DynamicMemoryStream;
|
|
|
|
m_mode = PlayBackMode;
|
|
|
|
lastReadSnapShot = 0;
|
|
lastReadPlayer = 0;
|
|
lastByteRead = 0;
|
|
totalLogSize = 0;
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void MissionReview::LoadLog(const char *file_name)
|
|
{
|
|
|
|
Verify(m_mode == PlayBackMode);
|
|
|
|
Stuff::FileStream file_stream(file_name);
|
|
|
|
|
|
if (ReadNames(&file_stream))
|
|
{
|
|
totalLogSize = 0;
|
|
file_stream.ReadBytes(&totalLogSize, 4);
|
|
|
|
//SPEW(("jerryeds", "SERVER TOTAL SIZE : %d", totalLogSize));
|
|
//SPEW(("jerryeds", "TOTAL SNAPSHOTS %d", m_totalSnapShots));
|
|
|
|
m_missionLog->WriteBytes(file_stream.GetPointer(), totalLogSize);
|
|
m_missionLog->Rewind();
|
|
|
|
// fill in the keyframe data...
|
|
for (int j = 0; j < m_totalSnapShots; ++j)
|
|
{
|
|
for (int i = 0; i < Maximum_Players; ++i)
|
|
{
|
|
if (m_playBackLog[i][j].m_playerStatus == MRPlayerData::InToken)
|
|
{
|
|
Scalar min_x = 0.0f;
|
|
Scalar max_x = 1.0f;
|
|
Scalar min_z = 0.0f;
|
|
Scalar max_z = 1.0f;
|
|
|
|
|
|
|
|
m_missionLog->ReadBitsToScaledFloat(m_playBackLog[i][j].m_position.x, min_x, max_x, XBitDepth);
|
|
m_missionLog->ReadBitsToScaledFloat(m_playBackLog[i][j].m_position.z, min_z, max_z, YBitDepth);
|
|
m_missionLog->ReadBitsToScaledFloat(m_playBackLog[i][j].m_yawRotation, -Stuff::Pi, Stuff::Pi, RotationBitDepth);
|
|
m_missionLog->ReadBits(&m_playBackLog[i][j].m_scoreBucket1, 32);
|
|
m_missionLog->ReadBits(&m_playBackLog[i][j].m_scoreBucket2, 32);
|
|
m_missionLog->ReadBits(&m_playBackLog[i][j].m_scoreBucket3, 32);
|
|
|
|
m_missionLog->ReadBit(m_playBackLog[i][j].m_takenDamage);
|
|
m_missionLog->ReadBit(m_playBackLog[i][j].m_firedWeapon);
|
|
m_missionLog->ReadBit(m_playBackLog[i][j].m_alive);
|
|
|
|
|
|
|
|
// SPEW (("afarrier","%d pos=%5.2f, %5.2f",j,m_playBackLog[i][j].m_position.x,m_playBackLog[i][j].m_position.z));
|
|
// SPEW (("afarrier","%d yaw=%5.2f",j,m_playBackLog[i][j].m_yawRotation));
|
|
|
|
for (int dz = 0; dz < MRPlayerData::Damage_Zones; ++dz)
|
|
{
|
|
m_missionLog->ReadBitsToScaledFloat(m_playBackLog[i][j].m_damageLevel[dz], 0.0f, 1.0f, DamageBitDepth);
|
|
}
|
|
|
|
m_missionLog->ReadByteAlign();
|
|
|
|
|
|
|
|
|
|
|
|
//SPEW(("jerryeds", "%d:%d -%d:%d - %d -%d:%d - %d- %f %f : %f", i, j, index, bit, data, index2, bit2, data2, m_playBackLog[i][j].m_position.x, m_playBackLog[i][j].m_position.y, m_playBackLog[i][j].m_yawRotation));
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
bool MissionReview::ReadNames(MemoryStream *stream)
|
|
{
|
|
|
|
Verify(m_mode == PlayBackMode);
|
|
|
|
if (stream->GetSize() > 20)
|
|
{
|
|
|
|
DWORD token;
|
|
stream->ReadBytes(&token, 4);
|
|
|
|
if (token == 0xAAAAAAAA)
|
|
{
|
|
haveHeaderInfo = true;
|
|
|
|
*stream >> missionName;
|
|
*stream >> minExtents >> maxExtents;
|
|
|
|
stream->ReadBytes(&m_totalSnapShots, 4);
|
|
m_bufferedSnapShots = m_totalSnapShots;
|
|
stream->ReadBytes(&m_snapShotFrequency, 4);
|
|
int size = 0;
|
|
stream->ReadBytes(&size, 4);
|
|
m_nameLog->AllocateBytes(size);
|
|
|
|
if (size > 0)
|
|
{
|
|
stream->ReadBytes(m_nameLog->GetPointer(), size);
|
|
}
|
|
|
|
|
|
for (int i = 0; i < Maximum_Players; ++i)
|
|
{
|
|
m_playBackLog[i] = new MRPlayerData[m_totalSnapShots];
|
|
}
|
|
|
|
|
|
// Fill in the name log data...
|
|
while(m_nameLog->GetBytesRemaining())
|
|
{
|
|
int token = 0;
|
|
m_nameLog->ReadBytes(&token, 1);
|
|
|
|
if (token == AddToken)
|
|
{
|
|
int snap_shot = 0;
|
|
int id = 0;
|
|
|
|
m_nameLog->ReadBytes(&snap_shot, 4);
|
|
m_nameLog->ReadBytes(&id, 1);
|
|
|
|
m_playBackLog[id][snap_shot].m_playerStatus = MRPlayerData::InToken;
|
|
|
|
int size = 0;
|
|
m_nameLog->ReadBytes(&size, 1);
|
|
m_playBackLog[id][snap_shot].m_playerName = (char *)m_nameLog->GetPointer();
|
|
m_nameLog->AdvancePointer(size);
|
|
|
|
}
|
|
else if (token == RemoveToken)
|
|
{
|
|
int snap_shot = 0;
|
|
int id = 0;
|
|
|
|
m_nameLog->ReadBytes(&snap_shot, 4);
|
|
m_nameLog->ReadBytes(&id, 1);
|
|
|
|
m_playBackLog[id][snap_shot].m_playerName = NULL;
|
|
m_playBackLog[id][snap_shot].m_playerStatus = MRPlayerData::OutToken;
|
|
|
|
}
|
|
else
|
|
{
|
|
STOP(("MISSION REVIEW LOG CORRUPT"));
|
|
}
|
|
}
|
|
|
|
//fill in the namelog gaps...
|
|
for (i = 0; i < Maximum_Players; ++i)
|
|
{
|
|
for (int j = 1; j < m_totalSnapShots; ++j)
|
|
{
|
|
if (m_playBackLog[i][j].m_playerStatus == MRPlayerData::NoChange)
|
|
{
|
|
m_playBackLog[i][j].m_playerStatus = m_playBackLog[i][j-1].m_playerStatus;
|
|
m_playBackLog[i][j].m_playerName = m_playBackLog[i][j-1].m_playerName;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void MissionReview::AddPartToLogBuffer(MemoryStream *log_part_stream)
|
|
{
|
|
Verify(m_mode == PlayBackMode);
|
|
|
|
|
|
|
|
|
|
if (m_nameLog->GetBufferBytesUsed() == 0)
|
|
{
|
|
//SPEW(("jerryeds", "SNAPSHOT-START"));
|
|
|
|
Verify(m_missionLog->GetBufferBytesUsed() == 0);
|
|
|
|
//m_nameLog->WriteBytes(log_part_stream->GetPointer(), log_part_stream->GetBytesRemaining());
|
|
//m_nameLog->Rewind();
|
|
ReadNames(log_part_stream);
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
//SPEW(("jerryeds", "ADDPART : %d", log_part_stream->GetBufferBytesUsed()));
|
|
|
|
Verify(m_nameLog->GetBufferBytesUsed() != 0);
|
|
|
|
// 12 + 12 + 5 + 32 + 32 + 1 + 1 + (12 * 4 )
|
|
|
|
|
|
// write the data
|
|
|
|
m_missionLog->SetPointer(m_missionLog->GetBufferBytesUsed());
|
|
m_missionLog->WriteBytes(log_part_stream->GetPointer(), log_part_stream->GetBufferBytesUsed());
|
|
|
|
// restore our last position
|
|
m_missionLog->SetPointer(lastByteRead);
|
|
|
|
//SPEW(("jerryeds", "SET LASTBYTE : %d", lastByteRead));
|
|
|
|
|
|
if (lastByteRead == 0)
|
|
{
|
|
totalLogSize = 0;
|
|
|
|
|
|
if (m_missionLog->GetBytesRemaining() > 4)
|
|
{
|
|
m_missionLog->ReadBytes(&totalLogSize, 4);
|
|
//SPEW(("jerryeds", "CLIENT TOTAL SIZE : %d", totalLogSize));
|
|
}
|
|
lastByteRead = 4;
|
|
}
|
|
|
|
//SPEW(("jerryeds", "REPORTED SIZE : %d, current size %d, packet size %d", totalLogSize, m_missionLog->GetBufferBytesUsed(), log_part_stream->GetBufferBytesUsed()));
|
|
|
|
//if (m_missionLog->GetBufferBytesUsed() >= totalLogSize)
|
|
{
|
|
|
|
|
|
int bits_per_sample = XBitDepth + YBitDepth + RotationBitDepth + 32 + 32 + 32 + 1 + 1 + 1 + (DamageBitDepth * MRPlayerData::Damage_Zones);
|
|
int bytes_per_sample;
|
|
|
|
if (bits_per_sample & 7)
|
|
{
|
|
bytes_per_sample = bits_per_sample >> 3;
|
|
++bytes_per_sample;
|
|
}
|
|
else
|
|
{
|
|
bytes_per_sample = bits_per_sample >> 3;
|
|
}
|
|
|
|
for (int j = lastReadSnapShot; j < m_totalSnapShots; ++j)
|
|
{
|
|
for (int i = lastReadPlayer; i < Maximum_Players; ++i)
|
|
{
|
|
if (m_missionLog->GetBytesRemaining() >= bytes_per_sample)
|
|
{
|
|
|
|
if (m_playBackLog[i][j].m_playerStatus == MRPlayerData::InToken)
|
|
{
|
|
Scalar min_x = 0.0f;
|
|
Scalar max_x = 1.0f;
|
|
Scalar min_z = 0.0f;
|
|
Scalar max_z = 1.0f;
|
|
|
|
|
|
|
|
m_missionLog->ReadBitsToScaledFloat(m_playBackLog[i][j].m_position.x, min_x, max_x, XBitDepth);
|
|
m_missionLog->ReadBitsToScaledFloat(m_playBackLog[i][j].m_position.z, min_z, max_z, YBitDepth);
|
|
m_missionLog->ReadBitsToScaledFloat(m_playBackLog[i][j].m_yawRotation, -Stuff::Pi, Stuff::Pi, RotationBitDepth);
|
|
m_missionLog->ReadBits(&m_playBackLog[i][j].m_scoreBucket1, 32);
|
|
m_missionLog->ReadBits(&m_playBackLog[i][j].m_scoreBucket2, 32);
|
|
m_missionLog->ReadBits(&m_playBackLog[i][j].m_scoreBucket3, 32);
|
|
|
|
m_missionLog->ReadBit(m_playBackLog[i][j].m_takenDamage);
|
|
m_missionLog->ReadBit(m_playBackLog[i][j].m_firedWeapon);
|
|
m_missionLog->ReadBit(m_playBackLog[i][j].m_alive);
|
|
|
|
for (int dz = 0; dz < MRPlayerData::Damage_Zones; ++dz)
|
|
{
|
|
m_missionLog->ReadBitsToScaledFloat(m_playBackLog[i][j].m_damageLevel[dz], 0.0f, 1.0f, DamageBitDepth);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_missionLog->ReadByteAlign();
|
|
|
|
|
|
//SPEW(("jerryeds", "%d:%d - %d:%d %d - %d:%d %d - %f %f : %f", i, j, index, bit, data ,index2, bit2, data2 ,m_playBackLog[i][j].m_position.x, m_playBackLog[i][j].m_position.y, m_playBackLog[i][j].m_yawRotation));
|
|
|
|
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// save where we are...
|
|
lastReadSnapShot = j;
|
|
lastReadPlayer = i;
|
|
lastByteRead = m_missionLog->GetIndex();
|
|
|
|
|
|
//SPEW(("jerryeds","LAST READ %d:%d - BYTE - %d", i, j, lastByteRead));
|
|
|
|
|
|
// in case it evenly ends...
|
|
if (totalLogSize == m_missionLog->GetBufferBytesUsed())
|
|
{
|
|
Verify(m_missionLog->GetBytesRemaining() == 0);
|
|
m_bufferedSnapShots = m_totalSnapShots;
|
|
|
|
//SPEW(("jerryeds","END LOG"));
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
lastReadPlayer = 0;
|
|
|
|
|
|
m_bufferedSnapShots = j;
|
|
//SPEW(("jerryeds", "SNAPSHOT %d", m_bufferedSnapShots));
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
char *MissionReview::GetMissionName()
|
|
{
|
|
return missionName;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void MissionReview::GetMapExtents(Point3D &min_extents, Point3D &max_extents)
|
|
{
|
|
min_extents = minExtents;
|
|
max_extents = maxExtents;
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
|
|
void MissionReview::GetLogTimes(Scalar &buffered_time, Scalar &total_time, Scalar &sample_rate)
|
|
{
|
|
Verify(m_mode == PlayBackMode);
|
|
|
|
buffered_time = m_bufferedSnapShots * m_snapShotFrequency;
|
|
total_time = m_totalSnapShots * m_snapShotFrequency;
|
|
sample_rate = m_snapShotFrequency;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void MissionReview::GetPlayerData(MRPlayerData *new_data, Scalar time, int player)
|
|
{
|
|
Verify(m_mode == PlayBackMode);
|
|
|
|
new_data->Reset();
|
|
|
|
int from_frame = 0;
|
|
int to_frame = 0;
|
|
Scalar lerp = 0.0f;
|
|
|
|
|
|
if (time < 0.0f || time >= (Scalar)(m_bufferedSnapShots*m_snapShotFrequency))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (m_bufferedSnapShots == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
from_frame = (int)(time / m_snapShotFrequency);
|
|
to_frame = from_frame + 1;
|
|
|
|
Clamp(from_frame, 0, m_bufferedSnapShots-1);
|
|
Clamp(to_frame, 0, m_bufferedSnapShots-1);
|
|
|
|
|
|
if (m_playBackLog[player][to_frame].m_playerStatus != MRPlayerData::InToken || to_frame == from_frame)
|
|
{
|
|
|
|
//SPEWALWAYS(("jerryeds", "PLAYER : %d : FRAME : %d", player, to_frame));
|
|
|
|
new_data->m_playerStatus = m_playBackLog[player][to_frame].m_playerStatus;
|
|
new_data->m_playerName = m_playBackLog[player][to_frame].m_playerName;
|
|
new_data->m_scoreBucket1 = m_playBackLog[player][to_frame].m_scoreBucket1;
|
|
new_data->m_scoreBucket2 = m_playBackLog[player][to_frame].m_scoreBucket2;
|
|
new_data->m_scoreBucket3 = m_playBackLog[player][to_frame].m_scoreBucket3;
|
|
|
|
new_data->m_takenDamage = m_playBackLog[player][to_frame].m_takenDamage;
|
|
new_data->m_firedWeapon = m_playBackLog[player][to_frame].m_firedWeapon;
|
|
new_data->m_alive = m_playBackLog[player][to_frame].m_alive;
|
|
|
|
for (int i = 0; i < MRPlayerData::Damage_Zones; ++i)
|
|
{
|
|
new_data->m_damageLevel[i] = m_playBackLog[player][to_frame].m_damageLevel[i];
|
|
}
|
|
new_data->m_yawRotation = m_playBackLog[player][to_frame].m_yawRotation;
|
|
new_data->m_position = m_playBackLog[player][to_frame].m_position;
|
|
return;
|
|
}
|
|
|
|
new_data->m_playerStatus = m_playBackLog[player][from_frame].m_playerStatus;
|
|
new_data->m_playerName = m_playBackLog[player][from_frame].m_playerName;
|
|
new_data->m_scoreBucket1 = m_playBackLog[player][from_frame].m_scoreBucket1;
|
|
new_data->m_scoreBucket2 = m_playBackLog[player][from_frame].m_scoreBucket2;
|
|
new_data->m_scoreBucket3 = m_playBackLog[player][from_frame].m_scoreBucket3;
|
|
|
|
new_data->m_takenDamage = m_playBackLog[player][from_frame].m_takenDamage;
|
|
new_data->m_firedWeapon = m_playBackLog[player][from_frame].m_firedWeapon;
|
|
new_data->m_alive = m_playBackLog[player][from_frame].m_alive;
|
|
|
|
for (int i = 0; i < MRPlayerData::Damage_Zones; ++i)
|
|
{
|
|
new_data->m_damageLevel[i] = m_playBackLog[player][from_frame].m_damageLevel[i];
|
|
}
|
|
|
|
lerp = ( time - (from_frame*m_snapShotFrequency) ) / m_snapShotFrequency;
|
|
|
|
Radian rotation;
|
|
rotation.Lerp(m_playBackLog[player][from_frame].m_yawRotation, m_playBackLog[player][to_frame].m_yawRotation, lerp);
|
|
new_data->m_yawRotation = rotation.angle;
|
|
new_data->m_position.Lerp(m_playBackLog[player][from_frame].m_position, m_playBackLog[player][to_frame].m_position, lerp);
|
|
|
|
}
|
|
#endif // !defined(NO_MR)
|