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.
556 lines
12 KiB
C++
556 lines
12 KiB
C++
//===========================================================================//
|
|
// File: Weapon_Tool.cpp
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 09/09/98 JSE Inital base class based off of Shadowrun/Adept
|
|
// 09/24/98 BDB Inital Weapon subsystem class based off of Subsystem_Tool.cpp
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1998, Fasa Interactive //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include "MW4Headers.hpp"
|
|
|
|
#include "Weapon.hpp"
|
|
#include "MWTool.hpp"
|
|
#include "MWDamageObject.hpp"
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Weapon__CreateMessage::ConstructCreateMessage(Script *script)
|
|
{
|
|
Check_Object(script);
|
|
|
|
//
|
|
//--------------
|
|
// Set up stream
|
|
//--------------
|
|
//
|
|
MemoryStream *message_stream = script->messageStream;
|
|
Check_Object(message_stream);
|
|
message_stream->AllocateBytes(sizeof(Weapon__CreateMessage));
|
|
Subsystem__CreateMessage::ConstructCreateMessage(script);
|
|
Weapon__CreateMessage *message =
|
|
Cast_Pointer(
|
|
Weapon__CreateMessage*,
|
|
message_stream->GetPointer()
|
|
);
|
|
message->messageLength = sizeof(*message);
|
|
|
|
//
|
|
//---------------------------
|
|
// Point at the notation file
|
|
//---------------------------
|
|
//
|
|
Page *page = script->instancePage;
|
|
Check_Object(page);
|
|
Check_Object(Tool::Instance);
|
|
|
|
const char *site_name;
|
|
page->GetEntry("Site", &site_name, true);
|
|
Check_Pointer(site_name);
|
|
Str_Copy(message->siteName, _strlwr((char*)site_name), sizeof(message->siteName));
|
|
|
|
const char *eject_site;
|
|
MString eject_site_name = " ";
|
|
if(page->GetEntry("EjectSite", &eject_site))
|
|
eject_site_name = eject_site;
|
|
// else
|
|
// eject_site_name = site_name;
|
|
Str_Copy(message->ejectSiteName, _strlwr((char*)eject_site_name), sizeof(message->ejectSiteName));
|
|
|
|
int ammo_count;
|
|
if(page->GetEntry("AmmoCount", &ammo_count))
|
|
{
|
|
message->ammoCount = ammo_count;
|
|
}
|
|
else
|
|
{
|
|
message->ammoCount = -1;
|
|
}
|
|
|
|
message->initialAmmoCount = message->ammoCount;
|
|
|
|
message->groupIndex = Weapon::DefaultWeaponGroupFlags;
|
|
ChainOf<Note*> *weapon_group = page->MakeNoteChain("GroupIndex");
|
|
Check_Object(weapon_group);
|
|
Page::NoteIterator weapon_group_list(weapon_group);
|
|
Note *weapon_name_entry;
|
|
while ((weapon_name_entry = weapon_group_list.ReadAndNext()) != NULL)
|
|
{
|
|
const char * weapon_group_num;
|
|
weapon_name_entry->GetEntry(&weapon_group_num);
|
|
int index = atoi(weapon_group_num);
|
|
switch(index)
|
|
{
|
|
case 1:
|
|
message->groupIndex |= Weapon::WeaponGroup1Flag;
|
|
break;
|
|
case 2:
|
|
message->groupIndex |= Weapon::WeaponGroup2Flag;
|
|
break;
|
|
case 3:
|
|
message->groupIndex |= Weapon::WeaponGroup3Flag;
|
|
break;
|
|
case 4:
|
|
message->groupIndex |= Weapon::WeaponGroup4Flag;
|
|
break;
|
|
case 5:
|
|
message->groupIndex |= Weapon::WeaponGroup5Flag;
|
|
break;
|
|
case 6:
|
|
message->groupIndex |= Weapon::WeaponGroup6Flag;
|
|
break;
|
|
}
|
|
}
|
|
delete weapon_group;
|
|
|
|
// MSL 5.04 Rear Firing Weapons
|
|
int weapon_facing = 0;
|
|
if(page->GetEntry("WeaponFacing", &weapon_facing))
|
|
{
|
|
message->m_weaponFacing = weapon_facing;
|
|
}
|
|
else
|
|
{
|
|
message->m_weaponFacing = 0;
|
|
}
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Weapon::SaveInstanceText(Page *instance_page)
|
|
{
|
|
Check_Object(this);
|
|
|
|
Subsystem::SaveInstanceText(instance_page);
|
|
|
|
instance_page->SetEntry("Site", (const char *)siteName);
|
|
// notation_file->SetEntry(instance_name, "GroupIndex", groupIndex);
|
|
if(IsInWeaponGroup1())
|
|
instance_page->AppendEntry("GroupIndex", "1");
|
|
if(IsInWeaponGroup2())
|
|
instance_page->AppendEntry("GroupIndex", "2");
|
|
if(IsInWeaponGroup3())
|
|
instance_page->AppendEntry("GroupIndex", "3");
|
|
if(IsInWeaponGroup4())
|
|
instance_page->AppendEntry("GroupIndex", "4");
|
|
if(IsInWeaponGroup5())
|
|
instance_page->AppendEntry("GroupIndex", "5");
|
|
if(IsInWeaponGroup6())
|
|
instance_page->AppendEntry("GroupIndex", "6");
|
|
|
|
int ammo_count = DECRYPT(encryptedAmmoCount);
|
|
instance_page->SetEntry("AmmoCount", ammo_count);
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Weapon__GameModel::ConstructGameModel(Script *script)
|
|
{
|
|
Check_Object(script);
|
|
|
|
//
|
|
//--------------
|
|
// Set up stream
|
|
//--------------
|
|
//
|
|
MemoryStream *model_stream = script->modelStream;
|
|
Check_Object(model_stream);
|
|
model_stream->AllocateBytes(sizeof(Weapon__GameModel));
|
|
Subsystem__GameModel::ConstructGameModel(script);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool
|
|
Weapon__GameModel::ReadAndVerify(
|
|
Weapon__GameModel *model,
|
|
ModelAttributeEntry *attribute_entry,
|
|
const char *data,
|
|
char **error,
|
|
int error_buffer
|
|
)
|
|
{
|
|
Check_Object(attribute_entry);
|
|
|
|
bool result = false;
|
|
bool valid_data = (*data != '\0');
|
|
|
|
//
|
|
//----------------------------------------
|
|
//Read in the values from the data entered
|
|
//----------------------------------------
|
|
//
|
|
result =
|
|
Subsystem__GameModel::ReadAndVerify(
|
|
model,
|
|
attribute_entry,
|
|
data,
|
|
error,
|
|
error_buffer
|
|
);
|
|
//
|
|
//---------------------------
|
|
//Verify all the model values
|
|
//---------------------------
|
|
//
|
|
switch(attribute_entry->attributeID)
|
|
{
|
|
case MuzzleFlashResourceAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
ResourceID value = ResourceID::Null;
|
|
attribute_entry->SetValue(model, (void *)&value);
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
case EjectEffectResourceAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
ResourceID value = ResourceID::Null;
|
|
attribute_entry->SetValue(model, (void *)&value);
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
case NumFireAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
int value = 1;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if (model->numFire <= 0)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]NumFire=%d}: value must be > 0!",
|
|
model->numFire
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case HudEffectAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 0.0;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if (model->m_HudEffect < 0.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]HudEffect=%d}: value must be > 0.0f!",
|
|
model->m_HudEffect
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case HeatAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 0.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
else
|
|
{
|
|
Scalar value = (Scalar)atof(data);
|
|
value /= 2;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
case HeatSpreadTimeAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 3.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->heatSpreadTime < 0.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]HeatSpreadTime=%f}: value must be > 0!",
|
|
model->heatSpreadTime
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case MaxAmmoAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
int value = 0;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->maxAmmoCount < 0)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]MaxAmmo=%f}: value must be >= 0!",
|
|
model->maxAmmoCount
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case AmmoPerShotAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
int value = 1;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->ammoPerShot <= 0.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]AmmoPerShot=%f}: value must be > 0!",
|
|
model->ammoPerShot
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case HeatToDealAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 0.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->heatToDeal < 0.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]HeatToDeal=%f}: value must be >= 0!",
|
|
model->heatToDeal
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case SplashRadiusAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 0.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->splashRadius < 0.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]SplashRadius=%f}: value must be >= 0!",
|
|
model->splashRadius
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
case PercentageOfDamageToDirectHitAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 0.4f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->percentageOfDamageToDirectHit < 0.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]PercentageOfDamageToDirectHit=%f}: value must be >= 0!",
|
|
model->percentageOfDamageToDirectHit
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case MinPercentageOfDamageToSphereHitAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 0.05f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->minPercentageOfDamageToSphereHit < 0.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]MinPercentageOfDamageToSphereHit=%f}: value must be >= 0!",
|
|
model->minPercentageOfDamageToSphereHit
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case MaxPercentageOfDamageToSphereHitAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 0.15f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->maxPercentageOfDamageToSphereHit < 0.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]MaxPercentageOfDamageToSphereHit=%f}: value must be >= 0!",
|
|
model->maxPercentageOfDamageToSphereHit
|
|
);
|
|
result = false;
|
|
}
|
|
|
|
|
|
break;
|
|
}
|
|
case DamageAmountAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 0.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if (model->damageAmount < 0)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]DamageAmount=%f}: value must be >= 0!",
|
|
model->damageAmount
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case MaxDistanceAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 300.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if (model->maxDistance <= 0)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]MaxDistance=%f}: value must be > 0!",
|
|
model->maxDistance
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
// MSL 5.03 Min Distance
|
|
// case MinDistanceAttributeID:
|
|
// {
|
|
// if(!valid_data)
|
|
// {
|
|
// Scalar value = 0.0f;
|
|
// attribute_entry->SetValue(model, &value);
|
|
// result = true;
|
|
// }
|
|
// if (model->minDistance < 0)
|
|
// {
|
|
// _snprintf(
|
|
// *error,
|
|
// error_buffer,
|
|
// "{[GameData]MinDistance=%f}: value must be >= 0!",
|
|
// model->minDistance
|
|
// );
|
|
// result = false;
|
|
// }
|
|
// break;
|
|
// }
|
|
case ReloadTimeAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 1.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if (model->reloadTime < 0.0)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]ReloadTime=%f}: value must be > 0!",
|
|
model->reloadTime
|
|
);
|
|
result = false;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case LightAmpFlareOutAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 0.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_lightAmpFlareOut < 0.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]LightAmpFlareOut=%f}: value must be >= 0!",
|
|
model->m_lightAmpFlareOut
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return result;
|
|
}
|