//===========================================================================// // 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 #include #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 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)