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.
592 lines
11 KiB
C++
592 lines
11 KiB
C++
|
|
#include "MW4Headers.hpp"
|
|
|
|
#include "AI_Log.hpp"
|
|
|
|
#include "aiutils.hpp"
|
|
#include "MWPlayer.hpp"
|
|
#include "VehicleInterface.hpp"
|
|
|
|
int g_objects_in_existence = 0;
|
|
|
|
using namespace MW4AI;
|
|
|
|
|
|
LogNode::LogNode(Type type, const std::string& text, const std::string& label)
|
|
: m_Text(text)
|
|
, m_Type(type)
|
|
, m_Label(label)
|
|
, m_Line(0)
|
|
{
|
|
Verify(type >= TYPE_FIRST);
|
|
Verify(type <= TYPE_LAST);
|
|
++g_objects_in_existence;
|
|
}
|
|
|
|
LogNode::LogNode(Type type, const std::string& text, const std::string& label, const std::string& filename, int line_number)
|
|
: m_Text(text)
|
|
, m_Type(type)
|
|
, m_Label(label)
|
|
, m_File(filename)
|
|
, m_Line(line_number)
|
|
{
|
|
Verify(type >= TYPE_FIRST);
|
|
Verify(type <= TYPE_LAST);
|
|
++g_objects_in_existence;
|
|
}
|
|
|
|
LogNode::~LogNode()
|
|
{
|
|
--g_objects_in_existence;
|
|
while (m_Children.size() > 0)
|
|
{
|
|
delete (*(m_Children.begin()));
|
|
m_Children.erase(m_Children.begin());
|
|
}
|
|
}
|
|
|
|
LogNode* LogNode::AddChild(Type type, const std::string& text, const std::string& label)
|
|
{
|
|
LogNode* new_node = new LogNode(type,text,label);
|
|
m_Children.push_back(new_node);
|
|
return (new_node);
|
|
}
|
|
|
|
LogNode* LogNode::AddChild(Type type, const std::string& text, const std::string& label, const std::string& filename, int line_number)
|
|
{
|
|
LogNode* new_node = new LogNode(type,text,label,filename,line_number);
|
|
m_Children.push_back(new_node);
|
|
return (new_node);
|
|
}
|
|
|
|
LogNode* LogNode::Find(const std::string& text)
|
|
{
|
|
{for (std::vector<LogNode*>::iterator i = m_Children.begin();
|
|
i != m_Children.end();
|
|
++i)
|
|
{
|
|
LogNode* found = (*i)->Find(text);
|
|
if (found != 0)
|
|
{
|
|
return (found);
|
|
}
|
|
}}
|
|
|
|
if (m_Text == text)
|
|
{
|
|
return (this);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
std::string LogNode::GetText() const
|
|
{
|
|
return (m_Text);
|
|
}
|
|
|
|
LogNode::Type LogNode::GetType() const
|
|
{
|
|
return (m_Type);
|
|
}
|
|
|
|
std::string LogNode::GetLabel() const
|
|
{
|
|
return (m_Label);
|
|
}
|
|
|
|
std::string LogNode::GetFile() const
|
|
{
|
|
return (m_File);
|
|
}
|
|
|
|
int LogNode::GetLine() const
|
|
{
|
|
return (m_Line);
|
|
}
|
|
|
|
void LogNode::SpewToString(std::string& output, unsigned int level, bool first_in_row) const
|
|
{
|
|
std::string prefix;
|
|
|
|
if (m_Text.size() > 0)
|
|
{
|
|
{for (unsigned int i = 0;
|
|
i < level;
|
|
++i)
|
|
{
|
|
prefix += " | ";
|
|
}}
|
|
|
|
if (GetType() == LogNode::TYPE_FUNCTION)
|
|
{
|
|
output += prefix;
|
|
}
|
|
|
|
output += m_Text;
|
|
|
|
if (m_Label.size() != 0)
|
|
{
|
|
output += " (";
|
|
output += m_Label;
|
|
output += ")";
|
|
}
|
|
|
|
if (m_File.size() != 0)
|
|
{
|
|
std::string f = m_File;
|
|
while (f.find('\\') != std::string::npos)
|
|
{
|
|
f.erase(0,1);
|
|
}
|
|
|
|
output += " [";
|
|
output += f;
|
|
output += ", line ";
|
|
output += IntToString(m_Line);
|
|
output += "]";
|
|
}
|
|
|
|
if (GetType() == LogNode::TYPE_FUNCTION)
|
|
{
|
|
output += "\n";
|
|
}
|
|
}
|
|
|
|
bool fDrawn = false;
|
|
{for (std::vector<LogNode*>::const_iterator i = m_Children.begin();
|
|
i != m_Children.end();
|
|
++i)
|
|
{
|
|
if ((*i)->GetType() == LogNode::TYPE_PARAMETER)
|
|
{
|
|
if (fDrawn == false)
|
|
{
|
|
output += prefix;
|
|
}
|
|
else
|
|
{
|
|
output += ", ";
|
|
}
|
|
|
|
(*i)->SpewToString(output,level+1);
|
|
fDrawn = true;
|
|
}
|
|
}}
|
|
|
|
{for (std::vector<LogNode*>::const_iterator i = m_Children.begin();
|
|
i != m_Children.end();
|
|
++i)
|
|
{
|
|
if ((*i)->GetType() == LogNode::TYPE_RETURN_VALUE)
|
|
{
|
|
if (fDrawn == false)
|
|
{
|
|
output += prefix;
|
|
}
|
|
else
|
|
{
|
|
output += ", ";
|
|
}
|
|
|
|
(*i)->SpewToString(output,level+1);
|
|
fDrawn = true;
|
|
}
|
|
}}
|
|
|
|
if (fDrawn == true)
|
|
{
|
|
output += "\n";
|
|
}
|
|
|
|
{for (std::vector<LogNode*>::const_iterator i = m_Children.begin();
|
|
i != m_Children.end();
|
|
++i)
|
|
{
|
|
if ((*i)->GetType() == LogNode::TYPE_FUNCTION)
|
|
{
|
|
(*i)->SpewToString(output,level+1);
|
|
}
|
|
}}
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
DiagnosticsInterface* DiagnosticsInterface::m_Instance = 0;
|
|
|
|
DiagnosticsInterface::DiagnosticsInterface()
|
|
: m_Enabled(false)
|
|
, m_ExecutingObject(0)
|
|
, m_FileAndLineEnabled(false)
|
|
, m_ParameterNamesEnabled(false)
|
|
, m_FileSpewing(false)
|
|
{
|
|
Verify(m_Instance == 0);
|
|
|
|
m_Instance = this;
|
|
m_Root.Assimilate(new LogNode(LogNode::TYPE_FUNCTION,""));
|
|
}
|
|
|
|
DiagnosticsInterface::~DiagnosticsInterface()
|
|
{
|
|
Verify(m_Instance == this);
|
|
|
|
m_Instance = 0;
|
|
}
|
|
|
|
void DiagnosticsInterface::Reset()
|
|
{
|
|
if (m_Root.GetPointer() != 0)
|
|
{
|
|
m_Root.Delete();
|
|
m_Root.Assimilate(new LogNode(LogNode::TYPE_FUNCTION,""));
|
|
}
|
|
}
|
|
|
|
DiagnosticsInterface& DiagnosticsInterface::GetInstance()
|
|
{
|
|
Verify(m_Instance != 0);
|
|
return (*m_Instance);
|
|
}
|
|
|
|
void DiagnosticsInterface::Log(LogNode::Type type, const std::string& value, const std::string& label)
|
|
{
|
|
if (CanLog() == false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
std::string l;
|
|
if ((GetParameterNamesEnabled() == true) ||
|
|
(type != LogNode::TYPE_PARAMETER))
|
|
{
|
|
l = label;
|
|
}
|
|
|
|
Verify(m_Stack.size() > 0);
|
|
|
|
m_Stack.back()->AddChild(type,value,l);
|
|
}
|
|
|
|
void DiagnosticsInterface::Log(LogNode::Type type, const Stuff::Scalar& value, const std::string& label)
|
|
{
|
|
if (CanLog() == false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Log(type,ScalarToString(value),label);
|
|
}
|
|
|
|
void DiagnosticsInterface::Log(LogNode::Type type, const Stuff::Point3D& value, const std::string& label)
|
|
{
|
|
if (CanLog() == false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
std::string s("(");
|
|
s += ScalarToString(value.x);
|
|
s += ",";
|
|
s += ScalarToString(value.y);
|
|
s += ",";
|
|
s += ScalarToString(value.z);
|
|
s += ")";
|
|
Log(type,s,label);
|
|
}
|
|
|
|
void DiagnosticsInterface::Log(LogNode::Type type, const int& value, const std::string& label)
|
|
{
|
|
if (CanLog() == false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Log(type,IntToString(value),label);
|
|
}
|
|
|
|
void DiagnosticsInterface::Log(LogNode::Type type, const bool& value, const std::string& label)
|
|
{
|
|
if (CanLog() == false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Log(type,BoolToString(value),label);
|
|
}
|
|
|
|
void DiagnosticsInterface::Log(LogNode::Type type, const TacticInterface::WR_WHO& value, const std::string& label)
|
|
{
|
|
if (CanLog() == false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
switch (value)
|
|
{
|
|
case TacticInterface::SELF:
|
|
{
|
|
Log(type,(std::string)"Self",label);
|
|
return;
|
|
}
|
|
case TacticInterface::TARGET:
|
|
{
|
|
Log(type,(std::string)"Target",label);
|
|
return;
|
|
}
|
|
}
|
|
|
|
Log(type,(std::string)"***INVALID***",label);
|
|
}
|
|
|
|
void DiagnosticsInterface::Log(LogNode::Type type, const TacticInterface::WR_QUALIFIER& value, const std::string& label)
|
|
{
|
|
if (CanLog() == false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
switch (value)
|
|
{
|
|
case TacticInterface::MIN:
|
|
{
|
|
Log(type,(std::string)"Min",label);
|
|
return;
|
|
}
|
|
case TacticInterface::MAX:
|
|
{
|
|
Log(type,(std::string)"Max",label);
|
|
return;
|
|
}
|
|
}
|
|
|
|
Log(type,(std::string)"***INVALID***",label);
|
|
}
|
|
|
|
void DiagnosticsInterface::Log(LogNode::Type type, const Stuff::Time& value, const std::string& label)
|
|
{
|
|
if (CanLog() == false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Log(type,ScalarToString((Stuff::Scalar)value),label);
|
|
}
|
|
|
|
void DiagnosticsInterface::Log(LogNode::Type type, const UserConstants::ID& value, const std::string& label)
|
|
{
|
|
if (CanLog() == false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Log(type,IntToString((int)value),label);
|
|
}
|
|
|
|
void DiagnosticsInterface::Log(LogNode::Type type, const FireStyles::FireStyleID& value, const std::string& label)
|
|
{
|
|
if (CanLog() == false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Log(type,FireStyles::FireStyleToString(value),label);
|
|
}
|
|
|
|
void DiagnosticsInterface::Log(LogNode::Type type, const FireData::HIT_RESULT& value, const std::string& label)
|
|
{
|
|
if (CanLog() == false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
switch (value)
|
|
{
|
|
case FireData::HIT_TARGET:
|
|
{
|
|
Log(type,(std::string)"HIT_TARGET",label);
|
|
return;
|
|
}
|
|
|
|
case FireData::HIT_SOMETHING_ELSE:
|
|
{
|
|
Log(type,(std::string)"HIT_SOMETHING_ELSE",label);
|
|
return;
|
|
}
|
|
|
|
case FireData::HIT_NOTHING:
|
|
{
|
|
Log(type,(std::string)"HIT_NOTHING",label);
|
|
return;
|
|
}
|
|
}
|
|
|
|
Log(type,(std::string)"***INVALID***",label);
|
|
}
|
|
|
|
void DiagnosticsInterface::PushFunction(const std::string& funcname, const std::string& file, int line)
|
|
{
|
|
if (CanLog() == false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
LogNode* new_node = 0;
|
|
|
|
if (m_Stack.size() == 0)
|
|
{
|
|
if (GetFileAndLineEnabled() == true)
|
|
{
|
|
new_node = m_Root->AddChild(LogNode::TYPE_FUNCTION,funcname,"",file,line);
|
|
}
|
|
else
|
|
{
|
|
new_node = m_Root->AddChild(LogNode::TYPE_FUNCTION,funcname);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (GetFileAndLineEnabled() == true)
|
|
{
|
|
new_node = m_Stack.back()->AddChild(LogNode::TYPE_FUNCTION,funcname,"",file,line);
|
|
}
|
|
else
|
|
{
|
|
new_node = m_Stack.back()->AddChild(LogNode::TYPE_FUNCTION,funcname);
|
|
}
|
|
}
|
|
|
|
m_Stack.push_back(new_node);
|
|
}
|
|
|
|
void DiagnosticsInterface::PopFunction(const std::string& funcname)
|
|
{
|
|
if (CanLog() == false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Verify(m_Stack.size() > 0);
|
|
Verify(m_Stack.back()->GetText() == funcname);
|
|
|
|
m_Stack.pop_back();
|
|
|
|
if (m_Stack.size() == 0)
|
|
{
|
|
if (m_Root.GetPointer() != 0)
|
|
{
|
|
m_BufferedSpew = "";
|
|
m_Root->SpewToString(m_BufferedSpew);
|
|
}
|
|
}
|
|
}
|
|
|
|
void DiagnosticsInterface::SetEnabled(bool enabled)
|
|
{
|
|
#ifdef LAB_ONLY
|
|
m_Enabled = enabled;
|
|
#endif
|
|
}
|
|
|
|
bool DiagnosticsInterface::GetEnabled() const
|
|
{
|
|
return (m_Enabled);
|
|
}
|
|
|
|
void DiagnosticsInterface::SetFileAndLineEnabled(bool enabled)
|
|
{
|
|
m_FileAndLineEnabled = enabled;
|
|
}
|
|
|
|
bool DiagnosticsInterface::GetFileAndLineEnabled() const
|
|
{
|
|
return (m_FileAndLineEnabled);
|
|
}
|
|
|
|
void DiagnosticsInterface::SetParameterNamesEnabled(bool enabled)
|
|
{
|
|
m_ParameterNamesEnabled = enabled;
|
|
}
|
|
|
|
bool DiagnosticsInterface::GetParameterNamesEnabled() const
|
|
{
|
|
return (m_ParameterNamesEnabled);
|
|
}
|
|
|
|
void DiagnosticsInterface::SetFileSpewing(bool enabled)
|
|
{
|
|
m_FileSpewing = enabled;
|
|
}
|
|
|
|
bool DiagnosticsInterface::GetFileSpewing() const
|
|
{
|
|
return (m_FileSpewing);
|
|
}
|
|
|
|
void DiagnosticsInterface::GetSpew(std::string& output) const
|
|
{
|
|
output = m_BufferedSpew;
|
|
}
|
|
|
|
Adept::Entity* GetPlayerVehicle()
|
|
{
|
|
if (Adept::Player::GetInstance() == 0)
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
MechWarrior4::MWPlayer* p = Cast_Object(MechWarrior4::MWPlayer*,Adept::Player::GetInstance());
|
|
if (p == 0)
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
Check_Object(p);
|
|
if (p->GetInterface() == 0)
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
return (p->GetInterface()->vehicle);
|
|
}
|
|
|
|
void DiagnosticsInterface::SetExecutingObject(MechWarrior4::MWObject* object)
|
|
{
|
|
m_ExecutingObject = object;
|
|
|
|
if ((m_ExecutingObject != 0) &&
|
|
(GetPlayerVehicle() != 0) &&
|
|
(m_ExecutingObject == GetPlayerVehicle()))
|
|
{
|
|
Reset();
|
|
}
|
|
}
|
|
|
|
bool DiagnosticsInterface::CanLog() const
|
|
{
|
|
if ((GetEnabled() == false) ||
|
|
(m_ExecutingObject == 0) ||
|
|
(GetPlayerVehicle() == 0))
|
|
{
|
|
return (false);
|
|
}
|
|
|
|
return (m_ExecutingObject == GetPlayerVehicle());
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
LogFunction::LogFunction(const std::string& name, const std::string& file, int line)
|
|
: m_Name(name)
|
|
{
|
|
DiagnosticsInterface::GetInstance().PushFunction(m_Name,file,line);
|
|
}
|
|
|
|
LogFunction::~LogFunction()
|
|
{
|
|
DiagnosticsInterface::GetInstance().PopFunction(m_Name);
|
|
}
|