Files
firestorm/Gameleap/code/mw4/Code/MW4/cultural.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

416 lines
10 KiB
C++

//===========================================================================//
// File: bridge.cpp
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/12/2000 AHF Inital base class
//===========================================================================//
#include "MW4Headers.hpp"
#include "cultural.hpp"
#include <adept\EntityManager.hpp>
#include "obstacle.hpp"
#include <adept\effect.hpp>
#include <adept\map.hpp>
#include <adept\damageobject.hpp>
#include "MWDamageObject.hpp"
#include <adept\application.hpp>
//#############################################################################
//############################### Cultural ############################
//#############################################################################
extern int g_nMR;
Cultural::ClassData* Cultural::DefaultData = NULL;
const Receiver::MessageEntry
Cultural::MessageEntries[]=
{
MESSAGE_ENTRY(Cultural, TakeDamage)
};
DWORD Cultural_Count = 0;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Cultural::InitializeClass()
{
Verify(!DefaultData);
DefaultData =
new ClassData(
CulturalClassID,
"MechWarrior4::Cultural",
Entity::DefaultData,
ELEMENTS(MessageEntries), MessageEntries,
(Entity::Factory)Make,
(Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
ExecutionStateEngine::DefaultData,
(Entity::GameModel::Factory)GameModel::ConstructGameModel,
(Entity::GameModel::Factory)GameModel::ConstructOBBStream,
(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
(Entity::GameModel::ModelWrite)GameModel::WriteToText,
(Entity::GameModel::ModelSave)GameModel::SaveGameModel
);
Register_Object(DefaultData);
DIRECT_GAME_MODEL_ATTRIBUTE(
Cultural__GameModel,
DeathEntityResource,
deathEntityResource,
ResourceID
);
DIRECT_GAME_MODEL_ATTRIBUTE(
Cultural__GameModel,
DestroyedEffectResource,
destroyedEffectResource,
ResourceID
);
DIRECT_GAME_MODEL_ATTRIBUTE(
Cultural__GameModel,
RammingDestroyedEffectResource,
rammingDestroyedEffectResource,
ResourceID
);
Cultural_Count = 0;
AddStatistic("Culturals", "culturals", gos_DWORD, &Cultural_Count, 0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void Cultural::TerminateClass()
{
Unregister_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Cultural* Cultural::Make(CreateMessage *message,ReplicatorID *base_id)
{
Cultural *new_entity = new Cultural(DefaultData, message, base_id, NULL);
Check_Object(new_entity);
return new_entity;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Cultural::Cultural(ClassData *class_data,CreateMessage *message,ReplicatorID *base_id,ElementRenderer::Element *element):
Entity(class_data, message, base_id, element)
{
Check_Pointer(this);
Check_Object(message);
Set_Statistic(Cultural_Count, Cultural_Count+1);
//
//--------------------------
// Create the damage Objects
//--------------------------
//
destroyableFlag = message->destroyableFlag;
//remove when content fixed
destroyableFlag = true;
lastHitType = RammingDamageFromAheadType;
delete executionState;
executionState = NULL;
if (Application::GetInstance()->applicationMode != Application::EditorMode)
{
NameTable *table = NameTable::GetInstance();
ObjectID id = table->FindID(instanceName);
table->SetName(id, NULL);
instanceName = NULL;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Cultural::~Cultural()
{
DESTRUCTOR("Cultural");
--Cultural_Count;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void Cultural::TestInstance()
{
Verify(IsDerivedFrom(DefaultData));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Cultural::Respawn(Entity::CreateMessage *message)
{
Check_Object(this);
Check_Object(message);
Entity::Respawn(message);
destroyableFlag = true;
lastHitType = RammingDamageFromAheadType;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Cultural::ReactToHit(const Entity__TakeDamageMessage *message,Adept::DamageObject *part_hit)
{
Check_Object(this);
Check_Object(message);
if (IsDestroyed())
return;
if (g_nMR == 2)
return;
//
// Save off the direction we were hit from as we have to initiate some destruction phases (trees) with knowledge of where
// we either were hit from, or run into from.
//
//
//
last_hit_normal = message->normal;
lastHitType = message->typeOfDamage;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Cultural::ReactToDestruction(int damage_mode, int damage_type)
{
Check_Object(this);
if(!IsDestroyed())
{
SetDestroyedFlag(damage_mode);
MW4AI::g_Rect4DHash->RemovePermRect (this);
const GameModel *model = GetGameModel();
Check_Object(model);
//
// Due to the network not being able to specify how something died, the trees need to do their differing
// reactions by whether they received a reactotohit message.
//
//
// Here we need to kick off the destruction effect with a normal from the direction of the damage
//
switch (lastHitType)
{
case BeamDamageType:
case MissileDamageType:
case ProjectileDamageType:
case SplashDamageType:
case HeatDamageType:
//
// don't use default here or it will always play the hit effect which we only want
// when shot.
//
// default:
CreateEffect(model->destroyedEffectResource, (Point3D)GetLocalToWorld(), last_hit_normal);
break;
/*
case RammingDamageFromAboveType:
case RammingDamageFromBelowType:
case RammingDamageFromLeftType:
case RammingDamageFromRightType:
case RammingDamageFromAheadType:
case RammingDamageFromBehindType:
case LavaDamageType;
case AmmoFireDamageType:
*/
}
CreateEffect(model->rammingDestroyedEffectResource, (Point3D)GetLocalToWorld(), last_hit_normal);
Entity *death_entity = CreateStaticHermitEntity(model->deathEntityResource);
if((death_entity) && (!m_deathEntity.GetCurrent()))
{
m_deathEntity.Remove();
m_deathEntity.Add(death_entity);
}
RemoveFromExecution();
}
Entity::ReactToDestruction(damage_mode, damage_type);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Effect*
Cultural::CreateEffect(const Adept::ResourceID& effect_id, const Point3D &location, const Normal3D &normal)
{
if (effect_id == ResourceID::Null)
return NULL;
Resource resource(effect_id);
Verify(resource.DoesResourceExist());
ClassID class_ID;
class_ID = Entity::GetClassIDFromDataListID(effect_id);
Verify(class_ID != NullClassID);
LinearMatrix4D effect_location = LinearMatrix4D::Identity;
effect_location.BuildTranslation(location);
Effect::CreateMessage effect_create_message(
sizeof(Effect::CreateMessage),
DefaultEventPriority,
Entity::CreateMessage::DefaultFlags,
class_ID,
Effect::DefaultFlags,
effect_id,
effect_location,
0.0f,
Entity::ExecutionStateEngine::AlwaysExecuteState,
NameTable::NullObjectID,
Entity::DefaultAlignment
);
MemoryStream stream(&effect_create_message, effect_create_message.messageLength);
Effect *entity;
ReplicatorID effect_rep_id = Connection::Hermit->GetNextReplicatorID();
entity = Cast_Object(Effect *,Entity::CreateEntity(&stream, &effect_rep_id, false));
Check_Object(entity);
Check_Object(Map::GetInstance());
Map::GetInstance()->AddChild(entity);
entity->SyncMatrices(true);
return entity;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Entity *
Cultural::CreateStaticHermitEntity(const Adept::ResourceID& entity_id)
{
if(entity_id == ResourceID::Null)
return false;
ClassID class_ID;
class_ID = GetClassIDFromDataListID(entity_id);
Verify(class_ID != NullClassID);
unsigned flags = HermitMode;
Entity::CreateMessage entity_create_message(
sizeof(Entity::CreateMessage),
DefaultEventPriority,
CreateMessage::DefaultFlags,
class_ID,
flags,
entity_id,
GetLocalToWorld(),
0.0f,
ExecutionStateEngine::NeverExecuteState,
NameTable::NullObjectID,
Entity::DefaultAlignment
);
MemoryStream stream(&entity_create_message, entity_create_message.messageLength);
Entity *entity;
ReplicatorID beam_id = Connection::Hermit->GetNextReplicatorID();
entity = CreateEntity(&stream, &beam_id, false);
Check_Object(entity);
entity->SetPropType(MissionPropType);
Map::GetInstance()->AddChild(entity);
entity->SyncMatrices(true);
return entity;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Cultural::RemoveFromExecution()
{
Check_Object(this);
Check_Object(entityElement);
//Check_Object(executionState);
//executionState->RequestState(ExecutionStateEngine::NeverExecuteState);
entityElement->SetAlwaysCullMode();
EntityManager::GetInstance()->RemovePostCollisionExecution(this);
RemoveCollision();
SyncMatrices(true);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void Cultural::ReactToInternalDamage(int damage_mode)
{
_asm nop;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Cultural::TakeDamageMessageHandler(const TakeDamageMessage *message)
{
Check_Object(this);
Check_Object(message);
Verify(message->messageID == TakeDamageMessageID);
if (IsDestroyable() && !IsDestroyed())
{
ReactToHit(message,NULL);
if (g_nMR != 2)
ReactToDestruction( InternalDamageObject::DestructionDamageMode, message->typeOfDamage);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
Cultural::IsNeverExecuteState()
{
return true;
}