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

449 lines
12 KiB
C++

//===========================================================================//
// File: Weapon.cpp
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 09/09/98 JSE Inital base class based off of Shadowrun/Adept //
// 09/24/98 BDB Inital Weapon subsytem class based off of Subsystem //
//---------------------------------------------------------------------------//
// Copyright (C) 1998, Fasa Interactive //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include "MW4Headers.hpp"
#include "SearchLight.hpp"
#include "MWObject.hpp"
#include "LightEntity.hpp"
#include "SubsystemClassData.hpp"
//#include "torso.hpp"
#include <Adept\Mission.hpp>
#include <Adept\Map.hpp>
#include <Adept\Effect.hpp>
#include <Adept\CollisionGrid.hpp>
#include <Adept\Site.hpp>
//#############################################################################
//############################### SearchLight ###########################
//#############################################################################
SearchLight::ClassData*
SearchLight::DefaultData = NULL;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
SearchLight::InitializeClass()
{
Verify(!DefaultData);
DefaultData =
new ClassData(
SearchLightClassID,
"MechWarrior4::SearchLight",
Subsystem::DefaultData,
0, NULL,
(Entity::Factory)Make,
(Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
ExecutionStateEngine::DefaultData,
(Entity::GameModel::Factory)GameModel::ConstructGameModel,
NULL,
(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
(Entity::GameModel::ModelWrite)GameModel::WriteToText,
(Entity::GameModel::ModelSave)GameModel::SaveGameModel,
(Subsystem::StreamCreate) CreateStream
);
Register_Object(DefaultData);
DIRECT_GAME_MODEL_ATTRIBUTE(
SearchLight__GameModel,
LightEntityResource,
lightEntityResource,
ResourceID
);
DIRECT_GAME_MODEL_ATTRIBUTE(
SearchLight__GameModel,
LightConeResource,
lightConeResource,
ResourceID
);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
SearchLight::TerminateClass()
{
Unregister_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
SearchLight*
SearchLight::Make(
CreateMessage *message,
ReplicatorID *base_id
)
{
Check_Object(message);
gos_PushCurrentHeap(Heap);
SearchLight *new_entity =
new SearchLight(DefaultData, message, base_id, NULL);
gos_PopCurrentHeap();
Check_Object(new_entity);
return new_entity;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Replicator::CreateMessage*
SearchLight::SaveMakeMessage(MemoryStream *stream, ResourceFile *res_file)
{
Check_Object(this);
Check_Object(stream);
stream->AllocateBytes(sizeof(CreateMessage));
Subsystem::SaveMakeMessage(stream, res_file);
CreateMessage *message =
Cast_Pointer(CreateMessage*, stream->GetPointer());
message->messageLength = sizeof(*message);
Str_Copy(message->siteName, (char *)siteName, sizeof(message->siteName));
return message;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
SearchLight::SearchLight(
ClassData *class_data,
CreateMessage *message,
ReplicatorID *base_id,
ElementRenderer::Element *element
):
Subsystem(class_data, message, base_id, element),
lightEntity(NULL),
lightConeEntity(NULL)
{
Check_Pointer(this);
Check_Object(message);
siteName = message->siteName;
sitePointer = NULL;
CommonCreation(message);
UsePostCollision();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
SearchLight::CommonCreation(CreateMessage *message)
{
Check_Object(this);
Check_Object(message);
if(!lightEntity.GetCurrent())
{
CreateSearchLight();
}
UsePostCollision();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
SearchLight::Respawn(Entity::CreateMessage *message)
{
Check_Object(this);
Check_Object(message);
Subsystem::Respawn(message);
CreateMessage *SearchLight_message = Cast_Pointer(CreateMessage *, message);
CommonCreation(SearchLight_message);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
SearchLight::~SearchLight()
{
HideBeam();
if(lightEntity.GetCurrent())
{
lightEntity.GetCurrent()->SentenceToDeathRow();
}
if(lightConeEntity.GetCurrent())
{
lightConeEntity.GetCurrent()->SentenceToDeathRow();
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
SearchLight::PostCollisionExecute(Time till)
{
Check_Object(this);
POSTCOLLISION_LOGIC("Subsystem::Searchlight");
//
// [johnyo] 08/27/00 PreviousSearchLight code is experimental code that I have checked in to keep a backup
// of only. It may be ripped out shortly if the effect that it was intended to have isn't
// put into the game
//
// if(Mission::GetInstance()->DoesAllowSearchLights() && isLightOn == true)
if(Mission::GetInstance()->DoesAllowSearchLights())
{
if(lightConeEntity.GetCurrent() == NULL)
{
const GameModel *model = GetGameModel();
Check_Object(model);
MWObject *parent = GetParentVehicle();
Check_Object(parent);
Check_Object(sitePointer);
lightConeEntity.Remove();
lightConeEntity.Add(
parent->CreateEffect(model->lightConeResource, sitePointer, true));
HideBeam();
}
if (
(lightEntity.GetCurrent()) &&
(lightEntity.GetCurrent()->lightIntensity > MidLevelRenderer::Limits::LightThreshold) &&
(sitePointer != 0)
)
{
Check_Object(sitePointer);
Point3D new_translation;
new_translation = sitePointer->GetLocalToWorld();
UnitVector3D direction_vector;
if(lightConeEntity.GetCurrent())
{
LinearMatrix4D new_position;
/*
YawPitchRoll angle;
// if (GetParentVehicle() && GetParentVehicle()->GetTorso())
// {
angle = lightConeEntity.GetCurrent()->effectOffset;
angle.yaw = 0.0f;
angle.roll = 0.0f;
// }
// else
// {
// angle = lightConeEntity.GetCurrent()->effectOffset;
// angle.yaw = 0.0f;
// angle.roll = 0.0f;
// angle.pitch += GetParentVehicle()->GetTorso()->eyePitch;
// }
LinearMatrix4D offset = lightConeEntity.GetCurrent()->effectOffset;
// offset.BuildRotation(angle);
new_position.Multiply(
offset,
sitePointer->GetLocalToWorld()
);
*/
new_position = lightConeEntity.GetCurrent()->GetLocalToWorld();
new_translation = lightConeEntity.GetCurrent()->GetLocalToWorld();
new_position.GetLocalLeftInWorld(&direction_vector);
}
else
{
sitePointer->GetLocalToWorld().GetLocalForwardInWorld(&direction_vector);
direction_vector.y -= 0.2f;
}
Line3D target_line;
Normal3D target_normal;
target_line.SetOrigin(new_translation);
target_line.SetDirection(direction_vector);
target_line.m_length = 500;
Entity::CollisionQuery target_query(&target_line, &target_normal, Entity::AlwaysCollidesMask, GetParentVehicle());
Adept::Entity *entity_hit;
Check_Object(CollisionGrid::Instance);
entity_hit = CollisionGrid::Instance->ProjectLine(&target_query);
Point3D light_point;
target_query.m_line->FindEnd(&light_point);
lightEntity.GetCurrent()->lightIntensity = target_query.m_line->m_length;
light_point.y = target_query.m_line->m_length/* - 0.01f*/;
// LinearMatrix4D new_local_to_world = sitePointer->GetLocalToWorld();
LinearMatrix4D new_local_to_world = lightConeEntity.GetCurrent()->GetLocalToWorld();
new_local_to_world.AlignLocalAxisToWorldVector(
direction_vector,
Stuff::Z_Axis,
Stuff::Y_Axis,
Stuff::X_Axis
);
// new_local_to_world.BuildTranslation(light_point);
lightEntity.GetCurrent()->SetNewLocalToParent(new_local_to_world);
lightEntity.GetCurrent()->SyncMatrices(true);
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool SearchLight::ConnectSubsystem()
{
MWObject *mw_object = GetParentVehicle();
Check_Object(mw_object);
sitePointer = mw_object->FindSite(siteName);
HideBeam();
//Must call the inherited virtual function!!!!
return Subsystem::ConnectSubsystem();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void SearchLight::CreateSearchLight()
{
Check_Object(this);
const GameModel *model = GetGameModel();
Check_Object(model);
if(model->lightEntityResource != ResourceID::Null)
{
ClassID class_ID;
class_ID = GetClassIDFromDataListID(model->lightEntityResource);
Verify(class_ID != NullClassID);
LightEntity::CreateMessage entity_create_message(
sizeof(Entity::CreateMessage),
DefaultEventPriority,
CreateMessage::DefaultFlags,
class_ID,
LightEntity::DefaultFlags,
model->lightEntityResource,
GetLocalToWorld(),
0.0f,
ExecutionStateEngine::AlwaysExecuteState,
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);
if(Map::GetInstance())
Map::GetInstance()->AddChild(entity);
lightEntity.Remove();
lightEntity.Add(Cast_Object(LightEntity *, entity));
entity->SyncMatrices(true);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
SearchLight::TakeCriticalHit()
{
Check_Object(this);
//Don't do anything here
return false;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void SearchLight::DestroySubsystem()
{
Check_Object(this);
Subsystem::DestroySubsystem();
HideBeam();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void SearchLight::HideBeam()
{
Check_Object(this);
if(lightEntity.GetCurrent())
{
// ElementRenderer::Element *element;
// element = lightEntity.GetCurrent()->GetElement();
// Check_Object(element);
// element->SetAlwaysCullMode();
lightEntity.GetCurrent()->lightIntensity = 0.0f;
}
if(lightConeEntity.GetCurrent())
{
ElementRenderer::Element *element;
element = lightConeEntity.GetCurrent()->GetElement();
Check_Object(element);
element->SetAlwaysCullMode();
}
isLightOn = false;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void SearchLight::ShowBeam()
{
Check_Object(this);
Check_Pointer(Mission::GetInstance());
if(Mission::GetInstance()->DoesAllowSearchLights())
{
if(lightEntity.GetCurrent())
{
lightEntity.GetCurrent()->lightIntensity = 1.0f;
}
if(lightConeEntity.GetCurrent())
{
ElementRenderer::Element *element;
element = lightConeEntity.GetCurrent()->GetElement();
Check_Object(element);
element->SetNeverCullMode();
}
isLightOn = true;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
SearchLight::TestInstance() const
{
Verify(IsDerivedFrom(DefaultData));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
SearchLight::CreateStream(ResourceID data_list, MemoryStream *stream)
{
Check_Pointer(stream);
stream->AllocateBytes(sizeof(SearchLight__CreateMessage));
Subsystem::CreateStream(data_list, stream);
SearchLight__CreateMessage *create_message = Cast_Pointer(
SearchLight__CreateMessage *, stream->GetPointer());
Str_Copy(create_message->siteName, _strlwr("site_light"), sizeof(create_message->siteName));
}