Files
firestorm/Gameleap/code/mw4/Code/MW4/CampaignMechLab.cpp
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
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.
2026-06-24 21:28:16 -05:00

658 lines
18 KiB
C++

#include "MW4Headers.hpp"
#pragma warning(disable:4100) // unreferenced formal parameter
#include "CampaignMechLab.hpp"
#include <gosScript\gosScriptHeaders.hpp>
#include "Mech.hpp"
#include "MWDamageObject.hpp"
#include "Subsystem.hpp"
#include "Weapon.hpp"
#include "MWMover.hpp"
#include "Armor.hpp"
#include "SubsystemClassData.hpp"
#include "Salvage.hpp"
#include "MWGame.hpp"
#include "MWApplication.hpp"
#include "MWTable.hpp"
#include <Adept\Entity.hpp>
#include <Adept\VideoRenderer.hpp>
#include <Adept\Site.hpp>
#include <ElementRenderer\CameraElement.hpp>
#include <ElementRenderer\StateChange.hpp>
#include <ElementRenderer\GroupElement.hpp>
#include <MLR\MLRTexturePool.hpp>
#include "..\buildnum\buildnum.h"
// jcem begin
#if 1 // jcem for MechView, CampaignMechLab.cpp too
#define CONN4ML (Connection::Hermit)
#else
#define CONN4ML (Connection::Local)
#endif
// jcem end
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CampaignMechLab::CampaignMechLab() :
MechLab()
{
// m_chassisCount = GetChassisCount();
m_isCampaign = 1;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CampaignMechLab::ReInitialize()
{
m_mechIDs = NULL;
m_chassisIDs = NULL;
DestroyWorkingEntity();
if(m_mechResourceFile.GetCurrent())
delete m_mechResourceFile.GetCurrent();
m_mechResourceFile.Remove();
m_mode = ChassisTabMode;
m_mechLabCount = GetMechCount();
m_chassisCount = GetChassisCount();
//Need to somehow make this a paramter so we can start with the current
//mech if there was one in the pilot place.
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CampaignMechLab::InitializeSubsystemsAvailable()
{
Check_Object(MWGame::GetInstance());
Check_Object(MWGame::GetInstance()->m_salvageManager);
SortedChainIteratorOf<SalvagePlug*, int> iterator(&MWGame::GetInstance()->m_salvageManager->m_salvageList);
SalvagePlug *salvage_plug;
while((salvage_plug = iterator.ReadAndNext()) != NULL)
{
Check_Object(salvage_plug);
Resource model_resource(salvage_plug->m_salvageID);
Verify(model_resource.DoesResourceExist());
Subsystem::GameModel *sub_model = Cast_Pointer(
Subsystem::GameModel *, model_resource.GetPointer());
//We are a Generic Sub and should be unlimmited
if((sub_model->itemID >= FirstGenericSubsystemID) && (sub_model->itemID <= LastGenericSubsystemID))
{
SubsystemResource *sub_resource;
sub_resource = AddAvailableSubsystem(
salvage_plug->m_dataListID,
salvage_plug->m_salvageID,
sub_model->itemID
);
Check_Object(sub_resource);
sub_resource->SetUnlimited();
}
else
{
//We need to check in with the salvage manager to get what is available!
for(int i=0; i<salvage_plug->m_count; i++)
{
AddAvailableSubsystem(
salvage_plug->m_dataListID,
salvage_plug->m_salvageID,
sub_model->itemID
);
}
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
CampaignMechLab::GetChassis(void* data[], int count)
{
Check_Pointer(this);
return 1;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
CampaignMechLab::GetChassisCount()
{
Check_Pointer(this);
Check_Object(MWGame::GetInstance());
Check_Object(MWGame::GetInstance()->m_salvageManager);
return 0;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int CampaignMechLab::GetMechCount()
{
Check_Pointer(this);
Check_Object(MWGame::GetInstance());
int count = 0;
SortedChainIteratorOf<MechTablePlug *, MString> iterator(&MWGame::GetInstance()->m_mechTable);
MechTablePlug *mech_plug;
while((mech_plug = iterator.ReadAndNext()) != NULL)
{
if(mech_plug->GetStatus() != MechTablePlug::DestroyedStatus)
{
count ++;
}
}
return count;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int CampaignMechLab::GetMechs(void* data[], int count)
{
Check_Pointer(this);
Check_Object(MWGame::GetInstance());
char **name_array = STRARRAYPARAM(1);
int *selected_mech = INTARRAYPARAM(2);
*selected_mech = 0; // jcem
if(m_mechLabCount > 0)
{
if(m_mechIDs)
{
gos_Free(m_mechIDs);
m_mechIDs = NULL;
}
m_mechIDs = (ResourceID *)gos_Malloc(m_mechLabCount * sizeof(ResourceID));
}
int i = 0;
SortedChainIteratorOf<MechTablePlug *, MString> iterator(&MWGame::GetInstance()->m_mechTable);
MechTablePlug *mech_plug;
while((mech_plug = iterator.ReadAndNext()) != NULL)
{
if(mech_plug->GetStatus() != MechTablePlug::DestroyedStatus)
{
FREEANDNULL(name_array[i]);
name_array[i] = (char *)gos_Malloc(128);
Str_Copy(
name_array[i],
(const char *)mech_plug->GetMechName(),
mech_plug->GetMechName().GetLength() + 1
);
m_mechIDs[i] = mech_plug->GetMechResourceID();
i++;
}
}
return 1;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
CampaignMechLab::SelectMech(void *data[], int count, const char *path)
{
Check_Pointer(this);
const char *mech_name = STRPARM(2);
MWGame::GetInstance()->ResetSalvageManager();
m_subsystemsAvailable.DeletePlugs();
InitializeSubsystemsAvailable();
int return_value = MechLab::SelectMech(data, count, "");
Check_Object(GetWorkingMech());
MechTablePlug *mech_plug = MWGame::GetInstance()->m_mechTable.Find(mech_name);
MWGame::GetInstance()->SetCurrentMechPlug(mech_plug);
m_workingMech->instanceName = mech_plug->GetOriginalName();
return return_value;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
CampaignMechLab::SaveMech()
{
//This needs to be done totally diferntly than that other one
if(GetWorkingMech())
{
Check_Object(MWGame::GetInstance());
DynamicMemoryStream stream;
m_workingMech->SaveMakeMessage(&stream, MWGame::GetInstance()->GetGameResourceFile());
stream.Rewind();
// Stuff::FileDependencies dependancies;
// dependancies.AddDependency("");
MechTablePlug *mech_plug = MWGame::GetInstance()->GetCurrentMechPlug();
Check_Object(mech_plug);
Resource mech_resource(mech_plug->GetMechResourceID());
mech_resource.Save(&stream, NULL);
}
MWGame::GetInstance()->SaveMWGame(MWGame::GetInstance()->GetGameName(), false);
MWGame::GetInstance()->ResetSalvageManager();
m_subsystemsAvailable.DeletePlugs();
InitializeSubsystemsAvailable();
//MWGame::GetInstance()->GetGameResourceFile()->Save();
return 1;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
CampaignMechLab::Exit()
{
// SaveMech();
Check_Object(MWGame::GetInstance());
MWGame::GetInstance()->ResetSalvageManager();
MWGame::GetInstance()->SaveMWGame(MWGame::GetInstance()->GetGameName(), false);
return MechLab::Exit();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
CampaignMechLab::CreateNewMech(void *data[], int count, const char *path)
{
Check_Pointer(this);
STOP(("SHOULD NEVER GET HERE!"));
return -1;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
CampaignMechLab::RemoveEquipmentFromList(Mech *mech)
{
Check_Pointer(this);
Check_Object(mech);
int return_value = 1;
ChainIteratorOf<Subsystem *> sub_iterator(&mech->subsystemsInVehicle);
Subsystem *subsystem;
while((subsystem = sub_iterator.ReadAndNext()) != NULL)
{
Check_Object(subsystem);
const Subsystem::GameModel *sub_model = subsystem->GetGameModel();
Check_Object(sub_model);
if(sub_model->itemID > -1)
{
if(DoesHaveAvailableSubsystem(sub_model->itemID))
{
//We have it in stock...now subtract it from stock
RemoveAvailableSubsystem(sub_model->itemID);
}
else
{
subsystem->DisconnectSubsystem();
subsystem->Destroy();
return_value = -1;
}
}
}
return return_value;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CampaignMechLab::AddEquipmentToList(Mech *mech)
{
Check_Pointer(this);
Check_Object(mech);
//Here we need to run through the mech equipment and re add it to our
//list of available stuff.
ChainIteratorOf<Subsystem *> sub_iterator(&mech->subsystemsInVehicle);
Subsystem *subsystem;
while((subsystem = sub_iterator.ReadAndNext()) != NULL)
{
Check_Object(subsystem);
const Subsystem::GameModel *sub_model = subsystem->GetGameModel();
Check_Object(sub_model);
if(sub_model->itemID > -1)
{
AddAvailableSubsystem(subsystem->GetDataListResourceID(),
subsystem->GetGameModelResourceID(),
sub_model->itemID
);
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CampaignMechLab::SetUpWorkingMech(Entity *entity)
{
Check_Pointer(this);
Check_Object(entity);
MechLab::SetUpWorkingMech(entity);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CampaignMechLab::AddSubsystemToMech(int *sub_type, int *zone, int *error)
{
MechLab::AddSubsystemToMech(sub_type, zone, error);
//Make sure that we added the subsystem!
if(GetWorkingMech() && (*error == 1))
{
Check_Object(m_workingMech);
MWInternalDamageObject *internal_zone;
internal_zone = m_workingMech->internalDamageObjects.Find(*zone);
Check_Object(internal_zone);
Subsystem *subsystem = internal_zone->GetSubsystem(*sub_type);
if((subsystem) && (*sub_type != Sub_HeatSink))
{
MWGame::GetInstance()->m_salvageManager->RemoveSalvage(subsystem);
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
CampaignMechLab::AutoAddSubsystem(void *data[], int count)
{
int *sub_type = INTARRAYPARAM(1);
int *error = INTARRAYPARAM(2);
*error = 1;
if(GetWorkingMech())
{
Check_Object(m_workingMech);
SubsystemResource *sub_resource = m_subsystemsAvailable.Find(*sub_type);
if(sub_resource)
{
Check_Object(sub_resource);
RegisteredClass::ClassID class_id = Entity::GetClassIDFromDataListID(sub_resource->GetDataListID());
Subsystem::ClassData *class_data =
Cast_Pointer(Subsystem::ClassData*, RegisteredClass::FindClassData(class_id));
Check_Object(class_data);
DynamicMemoryStream stream;
(*class_data->streamCreate)(sub_resource->GetDataListID(), &stream);
ReplicatorID base_id = Connection::Local->GetNextReplicatorID();
Subsystem__CreateMessage *create_message =
Cast_Pointer(Subsystem__CreateMessage *, stream.GetPointer());
//Ok now we have the subsystem stream...before we create we need to know where
//we want to put the thing.
Resource sub_model_resource(sub_resource->GetGameModelID());
Verify(sub_model_resource.DoesResourceExist());
Subsystem::GameModel *sub_model = Cast_Pointer(
Subsystem::GameModel *, sub_model_resource.GetPointer());
int slots_needed = sub_model->totalSlotsTaken;
int slot_type = sub_model->slotType;
//First check for a slot with the correct type, starting with the arms
int location = FindInternalLocation(slot_type, slots_needed);
//Next check for an omni slot starting with the arms
if(location == -1)
location = FindInternalLocation(MWInternalDamageObject::OmniSlotType, slots_needed);
if(location == -1)
{
*error = 0;
return 0;
}
//if no zone then exit!
create_message->locationID = (char)location;
Subsystem *subsystem =
Cast_Object(Subsystem *, Entity::CreateEntity(&stream, &base_id));
Check_Object(subsystem);
if(subsystem->IsDerivedFrom(Weapon::DefaultData))
{
Weapon *weapon = Cast_Object(Weapon *, subsystem);
MWInternalDamageObject *zone_object = m_workingMech->internalDamageObjects.Find(location);
Check_Object(zone_object);
Site *site = zone_object->GetNextWeaponSite();
if(!site)
{
*error = 0;
subsystem->Destroy();
return 0;
}
weapon->siteName = site->GetName();
}
m_workingMech->AddChild(subsystem);
m_workingMech->SyncMatrices(true);
if(subsystem->ConnectSubsystem())
{
m_workingMech->AddSubsystem(subsystem);
RemoveAvailableSubsystem(*sub_type);
MWGame::GetInstance()->m_salvageManager->RemoveSalvage(subsystem);
}
else
{
subsystem->Destroy();
*error = 0;
return 0;
}
}
else
{
*error = 0;
return 0;
}
}
MWApplication *app = MWApplication::GetInstance();
app->memoryDiffKiller.Init();
return 1;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CampaignMechLab::RemoveWeaponFromMech(int *sub_id, int *zone)
{
if(GetWorkingMech())
{
Check_Object(m_workingMech);
MWInternalDamageObject *internal_zone;
internal_zone = m_workingMech->internalDamageObjects.Find(*zone);
Check_Object(internal_zone);
// Subsystem *subsystem = internal_zone->subsystemChain.GetNth(*sub_id);
Subsystem *subsystem;
int weapon_count = 0;
ChainIteratorOf<Subsystem *> iterator(&internal_zone->subsystemChain);
while((subsystem = iterator.ReadAndNext()) != NULL)
{
Check_Object(subsystem);
if(subsystem->IsDerivedFrom(Weapon::DefaultData))
{
if(*sub_id == weapon_count)
{
//we need to get the subsystem name from the table using the model resource name
Check_Object(MWApplication::GetInstance());
MString sub_name = subsystem->GetModelName();
MWTableEntry *sub_entry =
MWApplication::GetInstance()->m_weaponsTable->FindEntryFromDataString(sub_name);
Check_Object(sub_entry);
MWGame::GetInstance()->m_salvageManager->AddSalvage(subsystem, sub_entry->GetEntryName());
}
else
{
weapon_count ++;
}
}
}
}
MechLab::RemoveWeaponFromMech(sub_id, zone);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CampaignMechLab::RemoveSubsystemFromMech(int *sub_type, int *zone)
{
if(GetWorkingMech())
{
Check_Object(m_workingMech);
MWInternalDamageObject *internal_zone;
internal_zone = m_workingMech->internalDamageObjects.Find(*zone);
Check_Object(internal_zone);
Subsystem *subsystem = internal_zone->GetSubsystem(*sub_type);
//Subsystem *subsystem = internal_zone->subsystemChain.GetNth(*sub_type);
if((subsystem)&& (*sub_type != Sub_HeatSink))
{
//we need to get the subsystem name from the table using the model resource name
Check_Object(MWApplication::GetInstance());
MString sub_name = subsystem->GetModelName();
MWTableEntry *sub_entry =
MWApplication::GetInstance()->m_subsystemTable->FindEntryFromDataString(sub_name);
Check_Object(sub_entry);
MWGame::GetInstance()->m_salvageManager->AddSalvage(subsystem, sub_entry->GetEntryName());
}
}
MechLab::RemoveSubsystemFromMech(sub_type, zone);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
CampaignMechLab::RemoveAllSubsystems()
{
if(GetWorkingMech())
{
Check_Object(m_workingMech);
ChainIteratorOf<Subsystem *> iterator(&m_workingMech->subsystemsInVehicle);
Subsystem *subsystem;
while((subsystem = iterator.ReadAndNext()) != NULL)
{
Check_Object(subsystem);
if(subsystem->IsDerivedFrom(Weapon::DefaultData))
{
//Disconnect, add to our reserves, and delete
Check_Object(MWApplication::GetInstance());
MString sub_name = subsystem->GetModelName();
MWTableEntry *sub_entry =
MWApplication::GetInstance()->m_weaponsTable->FindEntryFromDataString(sub_name);
if(!sub_entry)
{
//Check the subsystem one
sub_entry =
MWApplication::GetInstance()->m_subsystemTable->FindEntryFromDataString(sub_name);
}
Check_Object(sub_entry);
MWGame::GetInstance()->m_salvageManager->AddSalvage(subsystem, sub_entry->GetEntryName());
subsystem->DisconnectSubsystem();
m_workingMech->RemoveSubsystem(subsystem);
AddAvailableSubsystem(subsystem);
subsystem->Destroy();
}
}
//SaveMech();
return 1;
}
return 0;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
CampaignMechLab::Rename(void *data[], int count, const char *)
{
const char *chassis_name = STRPARM(1);
const char *mech_name = STRPARM(2);
MString new_name = MString(chassis_name)+" "+mech_name;
//new_name.ToLower();
MechTablePlug *mech_plug = MWGame::GetInstance()->GetCurrentMechPlug();
Check_Object(mech_plug);
MString old_name = mech_plug->GetMechName();
//old_name.ToLower();
if (new_name == old_name)
return 1;
if (MWGame::GetInstance()->m_mechTable.Find(new_name))
return E_MechAlreadyExists;
MWGame::GetInstance()->m_mechTable.Remove(mech_plug);
mech_plug->SetMechName(MString(chassis_name)+" "+mech_name);
MWGame::GetInstance()->m_mechTable.AddValue(mech_plug, new_name);
return 1;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int CampaignMechLab::Restore()
{
Check_Object(MWGame::GetInstance());
MWGame::GetInstance()->ResetSalvageManager();
m_subsystemsAvailable.DeletePlugs();
InitializeSubsystemsAvailable();
MechTablePlug *mech_plug = MWGame::GetInstance()->GetCurrentMechPlug();
DestroyWorkingEntity();
Resource mech_resource(mech_plug->GetMechResourceID());
Verify(mech_resource.DoesResourceExist());
ReplicatorID base_id = Connection::Local->GetNextReplicatorID();
Entity *entity;
entity = Entity::CreateEntity(&mech_resource, &base_id);
Check_Object(entity);
SetUpWorkingMech(entity);
m_workingMech->instanceName = mech_plug->GetOriginalName();
return 1;
}