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.
355 lines
8.3 KiB
C++
355 lines
8.3 KiB
C++
|
|
#include "MW4Headers.hpp"
|
|
|
|
#include "AI_Specials.hpp"
|
|
#include "aiutils.hpp"
|
|
#include <Adept\Resource.hpp>
|
|
#include "MWPlayer.hpp"
|
|
#include "VehicleInterface.hpp"
|
|
#include <gosfx\gosfx.hpp>
|
|
#include <Adept\Effect.hpp>
|
|
#include <Adept\Map.hpp>
|
|
|
|
|
|
|
|
using namespace MW4AI;
|
|
|
|
const Stuff::Scalar max_delay_between_fireworks = 2.5f;
|
|
const Stuff::Scalar max_fireworks_origin_skew = 40.0f;
|
|
|
|
|
|
Specials* Specials::m_Instance = 0;
|
|
|
|
Specials::Specials()
|
|
: m_RefCount(0)
|
|
, m_Resource("ai\\ai.specials")
|
|
, m_FireworksStopTime(0)
|
|
, m_NextFireworkStartTime(0)
|
|
, m_LaunchConfetti(false)
|
|
, m_ConfettiLaunched(false)
|
|
{
|
|
/*
|
|
Verify(m_Resource.DoesResourceExist());
|
|
|
|
m_Resource.Rewind();
|
|
m_NotationFile.Assimilate(new Stuff::NotationFile(&m_Resource));
|
|
|
|
m_FlareResource.Assimilate(new Adept::Resource(GetResourceName("Signal Flare","signal_flare").c_str()));
|
|
m_ConfettiResource.Assimilate(new Adept::Resource(GetResourceName("confetti","confetti").c_str()));
|
|
|
|
{
|
|
std::vector<std::string> resource_names;
|
|
GetResourceName_Multiple("Fireworks","firework",resource_names);
|
|
|
|
{for (std::vector<std::string>::const_iterator i = resource_names.begin();
|
|
i != resource_names.end();
|
|
++i)
|
|
{
|
|
Stuff::Auto_Ptr<Adept::Resource> temp(new Adept::Resource((*i).c_str()));
|
|
m_FireworksResource.push_back(temp);
|
|
}}
|
|
}
|
|
|
|
{
|
|
std::vector<std::string> resource_names;
|
|
GetResourceName_Multiple("Fighter Smoke","smoke",resource_names);
|
|
|
|
{for (std::vector<std::string>::const_iterator i = resource_names.begin();
|
|
i != resource_names.end();
|
|
++i)
|
|
{
|
|
Stuff::Auto_Ptr<Adept::Resource> temp(new Adept::Resource((*i).c_str()));
|
|
m_FighterSmoke.push_back(temp);
|
|
}}
|
|
}
|
|
*/
|
|
}
|
|
|
|
Specials::~Specials()
|
|
{
|
|
}
|
|
|
|
void Specials::IncrementRefCount()
|
|
{
|
|
if (m_Instance == 0)
|
|
{
|
|
m_Instance = new MW4AI::Specials();
|
|
}
|
|
|
|
++m_Instance->m_RefCount;
|
|
}
|
|
|
|
void Specials::DecrementRefCount()
|
|
{
|
|
Verify(m_Instance != 0);
|
|
Verify(m_Instance->m_RefCount > 0);
|
|
|
|
--(m_Instance->m_RefCount);
|
|
|
|
if (m_Instance->m_RefCount == 0)
|
|
{
|
|
delete m_Instance;
|
|
m_Instance = 0;
|
|
}
|
|
}
|
|
|
|
Specials* Specials::Instance()
|
|
{
|
|
return (m_Instance);
|
|
}
|
|
|
|
std::string Specials::GetResourceName(const std::string& block_name, const std::string& item_name)
|
|
{
|
|
Verify(m_NotationFile.GetPointer() != 0);
|
|
|
|
Stuff::Page* page = m_NotationFile->FindPage(block_name.c_str());
|
|
|
|
if (page == 0)
|
|
{
|
|
Verify(!"Item not found. Make sure you have the latest CONTENT\\AI\\AI.SPECIALS file.");
|
|
return ("");
|
|
}
|
|
|
|
Stuff::Note* note = page->FindNote(item_name.c_str());
|
|
|
|
if (note == 0)
|
|
{
|
|
Verify(!"Item not found.");
|
|
return ("");
|
|
}
|
|
|
|
const char* rv;
|
|
note->GetEntry(&rv);
|
|
return (rv);
|
|
}
|
|
|
|
void Specials::GetResourceName_Multiple(const std::string& block_name, const std::string& item_name, std::vector<std::string>& resource_names)
|
|
{
|
|
Verify(m_NotationFile.GetPointer() != 0);
|
|
|
|
Stuff::Page* page = m_NotationFile->FindPage(block_name.c_str());
|
|
|
|
if (page == 0)
|
|
{
|
|
Verify(!"Item not found. Make sure you have the latest CONTENT\\AI\\AI.SPECIALS file.");
|
|
return;
|
|
}
|
|
|
|
Stuff::Note* note_total = page->FindNote("total");
|
|
if (note_total == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int total;
|
|
note_total->GetEntry(&total);
|
|
Verify(total >= 0);
|
|
|
|
{for (int i = 0;
|
|
i < total;
|
|
++i)
|
|
{
|
|
std::string modified_item_name(item_name);
|
|
modified_item_name += IntToString(i);
|
|
|
|
Stuff::Note* note = page->FindNote(modified_item_name.c_str());
|
|
|
|
if (note == 0)
|
|
{
|
|
Verify(!"Item not found.");
|
|
}
|
|
else
|
|
{
|
|
const char* resource_name;
|
|
note->GetEntry(&resource_name);
|
|
resource_names.push_back(resource_name);
|
|
}
|
|
}}
|
|
}
|
|
|
|
MWObject* Specials::GetPlayerVehicle()
|
|
{
|
|
if (Adept::Player::GetInstance() == 0)
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
MechWarrior4::MWPlayer* p = Cast_Object(MechWarrior4::MWPlayer*,Adept::Player::GetInstance());
|
|
if ((p == 0) ||
|
|
(p->GetInterface() == 0))
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
return (p->GetInterface()->vehicle);
|
|
}
|
|
|
|
int Specials::GetNumFireworkTypes() const
|
|
{
|
|
return (m_FireworksResource.size());
|
|
}
|
|
|
|
void Specials::LaunchSignalFlare(const Stuff::Point3D& pos)
|
|
{
|
|
// m_QueuedSignalFlares.push_back(pos);
|
|
}
|
|
|
|
void Specials::LaunchFirework(unsigned int type, const Stuff::Point3D& pos)
|
|
{
|
|
/*
|
|
if (type > m_FireworksResource.size())
|
|
{
|
|
return;
|
|
}
|
|
|
|
Adept::Resource* resource = m_FireworksResource[type];
|
|
|
|
if ((GetPlayerVehicle() == 0) ||
|
|
(resource == 0) ||
|
|
(resource->GetResourceID() == ResourceID::Null))
|
|
{
|
|
return;
|
|
}
|
|
|
|
GetPlayerVehicle()->CreateEffect(resource->GetResourceID(),pos);
|
|
*/
|
|
}
|
|
|
|
void Specials::LaunchFireworks(const Stuff::Point3D& pos, int duration)
|
|
{
|
|
/*
|
|
m_FireworksStopTime = (Stuff::Time)gos_GetElapsedTime() + (Stuff::Time)duration;
|
|
m_NextFireworkStartTime = (Stuff::Time)gos_GetElapsedTime() + GetTimeToNextFirework();
|
|
m_FireworksOrigin = pos;
|
|
*/
|
|
}
|
|
|
|
void Specials::LaunchConfetti()
|
|
{
|
|
if (m_ConfettiLaunched == false)
|
|
{
|
|
m_LaunchConfetti = true;
|
|
}
|
|
}
|
|
|
|
void Specials::Update()
|
|
{
|
|
/*
|
|
if (GetPlayerVehicle() != 0)
|
|
{
|
|
if ((m_FlareResource.GetPointer() != 0) &&
|
|
(m_FlareResource->GetResourceID() != ResourceID::Null))
|
|
{
|
|
while (m_QueuedSignalFlares.size() > 0)
|
|
{
|
|
GetPlayerVehicle()->CreateEffect(m_FlareResource->GetResourceID(),*(m_QueuedSignalFlares.begin()));
|
|
m_QueuedSignalFlares.erase(m_QueuedSignalFlares.begin());
|
|
}
|
|
}
|
|
|
|
if (m_LaunchConfetti == true)
|
|
{
|
|
if ((m_ConfettiResource.GetPointer() != 0) &&
|
|
(m_ConfettiResource->GetResourceID() != ResourceID::Null))
|
|
{
|
|
MechWarrior4::MWPlayer* p = Cast_Object(MechWarrior4::MWPlayer*,Adept::Player::GetInstance());
|
|
if ((p != 0) &&
|
|
(p->GetInterface() != 0))
|
|
{
|
|
p->GetInterface()->CreateWeatherEffect(m_ConfettiResource->GetResourceID());
|
|
}
|
|
}
|
|
|
|
m_LaunchConfetti = false;
|
|
m_ConfettiLaunched = true;
|
|
}
|
|
}
|
|
|
|
if (gos_GetElapsedTime() < m_FireworksStopTime)
|
|
{
|
|
int iters = 0;
|
|
while (m_NextFireworkStartTime < gos_GetElapsedTime())
|
|
{
|
|
LaunchRandomFirework();
|
|
m_NextFireworkStartTime += GetTimeToNextFirework();
|
|
|
|
++iters;
|
|
if (iters > 4)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
Stuff::Time Specials::GetTimeToNextFirework() const
|
|
{
|
|
return (Stuff::Random::GetFraction() * max_delay_between_fireworks);
|
|
}
|
|
|
|
void Specials::LaunchRandomFirework()
|
|
{
|
|
/*
|
|
Stuff::Point3D pos(m_FireworksOrigin);
|
|
OffsetTargetPoint(pos,max_fireworks_origin_skew);
|
|
|
|
LaunchFirework(gos_rand() % m_FireworksResource.size(),pos);
|
|
*/
|
|
}
|
|
|
|
void Specials::LaunchFighterSmoke(MechWarrior4::MWObject& mwobject, int smoke_index)
|
|
{
|
|
/*
|
|
Check_Pointer(this);
|
|
|
|
AttachSmoke(mwobject,smoke_index,Stuff::Point3D(-11,0,0));
|
|
AttachSmoke(mwobject,smoke_index,Stuff::Point3D(11,0,0));
|
|
*/
|
|
}
|
|
|
|
void Specials::AttachSmoke(MechWarrior4::MWObject& mwobject, int smoke_index, const Stuff::Point3D& offset)
|
|
{
|
|
if ((smoke_index > m_FighterSmoke.size()) ||
|
|
(m_FighterSmoke[smoke_index]->DoesResourceExist() == false))
|
|
{
|
|
return;
|
|
}
|
|
|
|
MechWarrior4::MWObject::ClassID class_ID;
|
|
class_ID = Adept::Entity::GetClassIDFromDataListID(m_FighterSmoke[smoke_index]->GetResourceID());
|
|
Verify(class_ID != NullClassID);
|
|
|
|
LinearMatrix4D initial_position = LinearMatrix4D::Identity;
|
|
initial_position.Multiply(gosFX::Effect_Against_Motion, mwobject.GetElement()->GetNewLocalToParent());
|
|
|
|
Adept::Effect::CreateMessage effect_create_message(
|
|
sizeof(Effect::CreateMessage),
|
|
DefaultEventPriority,
|
|
MechWarrior4::MWObject::CreateMessage::DefaultFlags,
|
|
class_ID,
|
|
Effect::DefaultFlags|Effect::LoopFlag,
|
|
m_FighterSmoke[smoke_index]->GetResourceID(),
|
|
initial_position,
|
|
0.0f,
|
|
MechWarrior4::MWObject::ExecutionStateEngine::AlwaysExecuteState,
|
|
NameTable::NullObjectID,
|
|
Entity::DefaultAlignment
|
|
);
|
|
MemoryStream stream(&effect_create_message, effect_create_message.messageLength);
|
|
|
|
Entity *entity;
|
|
ReplicatorID trail_id = Connection::Hermit->GetNextReplicatorID();
|
|
entity = mwobject.CreateEntity(&stream, &trail_id, false);
|
|
Check_Object(entity);
|
|
Check_Object(Adept::Map::GetInstance());
|
|
Adept::Map::GetInstance()->AddChild(entity);
|
|
Effect* effect = Cast_Object(Effect*,entity);
|
|
effect->SetFollowEntity(&mwobject);
|
|
|
|
effect->effectOffset.BuildTranslation(offset);
|
|
|
|
effect->executionState->RequestState(Effect::ExecutionStateEngine::RunningState);
|
|
effect->SyncMatrices(true);
|
|
}
|