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.
829 lines
21 KiB
C++
829 lines
21 KiB
C++
|
|
#include "MW4Headers.hpp"
|
|
|
|
#include "BeamEntity.hpp"
|
|
#include <Adept\EntityClassData.hpp>
|
|
#include "MWPlayer.hpp"
|
|
#include "VehicleInterface.hpp"
|
|
#include <Adept\Effect.hpp>
|
|
#include <Adept\Map.hpp>
|
|
#include "MWMover.hpp"
|
|
#include "MWObject.hpp"
|
|
#include <Adept\NameTable.hpp>
|
|
#include "Decal.hpp"
|
|
#include "MWDamageObject.hpp"
|
|
#include <Adept\CollisionGrid.hpp>
|
|
#include <Adept\VideoRenderer.hpp>
|
|
#include <Adept\EntityManager.hpp>
|
|
#include <Adept\Site.hpp>
|
|
#include "mwmission.hpp"
|
|
#include "bucket.hpp"
|
|
#include "MWApplication.hpp"
|
|
|
|
//#############################################################################
|
|
//############################### BeamEntity ############################
|
|
//#############################################################################
|
|
|
|
BeamEntity::ClassData*
|
|
BeamEntity::DefaultData = NULL;
|
|
|
|
DWORD MechWarrior4::Executed_Beam_Count = 0;
|
|
|
|
#define HUNT_ADD_EFFECT_BUG
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
BeamEntity::InitializeClass()
|
|
{
|
|
Verify(!DefaultData);
|
|
DefaultData =
|
|
new ClassData(
|
|
BeamEntityClassID,
|
|
"MechWarrior4::BeamEntity",
|
|
BaseClass::DefaultData,
|
|
0, NULL,
|
|
(Entity::Factory)Make,
|
|
NULL,
|
|
ExecutionStateEngine::DefaultData,
|
|
(Entity::GameModel::Factory)GameModel::ConstructGameModel,
|
|
NULL,
|
|
(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
|
|
(Entity::GameModel::ModelWrite)GameModel::WriteToText,
|
|
(Entity::GameModel::ModelSave)GameModel::SaveGameModel
|
|
);
|
|
Register_Object(DefaultData);
|
|
|
|
CUSTOM_DIRECT_ATTRIBUTE(
|
|
BeamEntity,
|
|
BeamDistance,
|
|
beamDistanceAttribute,
|
|
Scalar,
|
|
ScalarClassID
|
|
);
|
|
|
|
CUSTOM_DIRECT_ATTRIBUTE(
|
|
BeamEntity,
|
|
TargetPoint,
|
|
targetPoint,
|
|
Point3D,
|
|
Point3DClassID
|
|
);
|
|
|
|
CUSTOM_DIRECT_ATTRIBUTE(
|
|
BeamEntity,
|
|
BeamHitSFX,
|
|
beamHitSFX,
|
|
int,
|
|
IntClassID
|
|
);
|
|
|
|
CUSTOM_DIRECT_ATTRIBUTE(
|
|
BeamEntity,
|
|
BeamStatus,
|
|
beamStatus,
|
|
bool,
|
|
BoolClassID
|
|
);
|
|
|
|
DIRECT_GAME_MODEL_ATTRIBUTE(
|
|
BeamEntity__GameModel,
|
|
HitEffectResource,
|
|
hitEffectResourceID,
|
|
ResourceID
|
|
);
|
|
|
|
DIRECT_GAME_MODEL_ATTRIBUTE(
|
|
BeamEntity__GameModel,
|
|
DamageDecalResource,
|
|
damageDecalResourceID,
|
|
ResourceID
|
|
);
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
BeamEntity::TerminateClass()
|
|
{
|
|
Unregister_Object(DefaultData);
|
|
delete DefaultData;
|
|
DefaultData = NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
BeamEntity*
|
|
BeamEntity::Make(
|
|
CreateMessage *message,
|
|
ReplicatorID *base_id
|
|
)
|
|
{
|
|
gos_PushCurrentHeap(Heap);
|
|
Check_Object(EntityManager::GetInstance());
|
|
BeamEntity *new_entity;
|
|
Entity *entity = EntityManager::GetInstance()->RequestFromArmory(message->dataListID);
|
|
if (entity)
|
|
{
|
|
new_entity = Cast_Object(BeamEntity*, entity);
|
|
new_entity->Reuse(message, base_id);
|
|
}
|
|
else
|
|
new_entity = new BeamEntity(DefaultData, message, base_id, NULL);
|
|
gos_PopCurrentHeap();
|
|
Check_Object(new_entity);
|
|
return new_entity;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
BeamEntity::BeamEntity(
|
|
ClassData *class_data,
|
|
CreateMessage *message,
|
|
ReplicatorID *base_id,
|
|
ElementRenderer::Element *element
|
|
):
|
|
Entity(class_data, message, base_id, element),
|
|
siteEntity(NULL),
|
|
targetEntity(NULL)
|
|
{
|
|
Check_Pointer(this);
|
|
Check_Object(message);
|
|
Check_Object(Connection::Local);
|
|
|
|
inflictingEntityID = message->inflictingEntityID;
|
|
|
|
if (MWApplication::GetInstance()->networkingFlag == true)
|
|
{
|
|
MWMission *mission;
|
|
Check_Object (MWMission::GetInstance());
|
|
mission = Cast_Object (MWMission *,MWMission::GetInstance());
|
|
mission->m_BucketManager->NotifyAction (CBucketManager::SHOTS_FIRED,inflictingEntityID,1);
|
|
}
|
|
|
|
// find the entity and connect to it
|
|
Check_Object(Network::GetInstance());
|
|
Connection *connection = Network::GetInstance()->GetConnection(inflictingEntityID.connectionID);
|
|
Check_Object(connection);
|
|
|
|
Replicator *replicator;
|
|
replicator = connection->FindReplicator(inflictingEntityID);
|
|
|
|
Verify(replicator->IsDerivedFrom(MWObject::DefaultData));
|
|
inflictingVehicle = Cast_Object(MWObject *, replicator);
|
|
|
|
Site *site = inflictingVehicle->m_sites.Find(message->siteName);
|
|
Check_Object(site);
|
|
|
|
siteEntity.Add(site);
|
|
targetOffset = Stuff::Point3D::Identity;
|
|
if(message->targetID != ReplicatorID::Null)
|
|
{
|
|
|
|
Check_Object(Network::GetInstance());
|
|
Connection *connection = Network::GetInstance()->GetConnection(message->targetID.connectionID);
|
|
if (connection)
|
|
{
|
|
Check_Object(connection);
|
|
|
|
Replicator *rep = connection->FindReplicator(message->targetID);
|
|
|
|
if (rep)
|
|
{
|
|
targetEntity.Add(Cast_Object(
|
|
Entity*,
|
|
rep
|
|
));
|
|
|
|
//
|
|
// If we have an entity we are locked on then targetPoint is the offset from the object itself
|
|
// we save this to use later in the raycast testing against where the object is now.
|
|
//
|
|
//
|
|
// Make targetOffset the difference from the target entity to the point
|
|
//
|
|
targetOffset.MultiplyByInverse(message->targetPoint, targetEntity.GetCurrent()->GetLocalToWorld());
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
targetPoint = message->targetPoint;
|
|
targetNormal = message->targetNormal;
|
|
damageAmount = message->damageAmount;
|
|
targetMaterial = message->targetMaterial;
|
|
heatAmount = message->heatAmount;
|
|
maxDistance = message->maxDistance;
|
|
// MSL 5.03 Min Distance
|
|
// minDistance = message->minDistance;
|
|
|
|
itemID = message->itemID;
|
|
|
|
Check_Object(siteEntity.GetCurrent());
|
|
beamHitSFX = 0;
|
|
CommonConstructor();
|
|
|
|
lastParameterization = gos_GetElapsedTime();
|
|
// firstFrame = true;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
BeamEntity::~BeamEntity()
|
|
{
|
|
DESTRUCTOR("BeamEntity");
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
BeamEntity::Reuse(
|
|
const CreateMessage *message,
|
|
ReplicatorID *base_id
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
BaseClass::Reuse(message, base_id);
|
|
|
|
Check_Pointer(this);
|
|
Check_Object(message);
|
|
Check_Object(Connection::Local);
|
|
|
|
// find the entity and connect to it
|
|
inflictingEntityID = message->inflictingEntityID;
|
|
|
|
// find the entity and connect to it
|
|
Check_Object(Network::GetInstance());
|
|
Connection *connection = Network::GetInstance()->GetConnection(inflictingEntityID.connectionID);
|
|
Check_Object(connection);
|
|
|
|
Replicator *replicator;
|
|
replicator = connection->FindReplicator(inflictingEntityID);
|
|
|
|
Verify(replicator->IsDerivedFrom(MWObject::DefaultData));
|
|
inflictingVehicle = Cast_Object(MWObject *, replicator);
|
|
|
|
Site *site = inflictingVehicle->m_sites.Find(message->siteName);
|
|
Check_Object(site);
|
|
|
|
siteEntity.Remove();
|
|
siteEntity.Add(site);
|
|
targetOffset = Stuff::Point3D::Identity;
|
|
|
|
if(message->targetID != ReplicatorID::Null)
|
|
{
|
|
|
|
Check_Object(Network::GetInstance());
|
|
Connection *connection = Network::GetInstance()->GetConnection(message->targetID.connectionID);
|
|
if (connection)
|
|
{
|
|
Check_Object(connection);
|
|
|
|
Replicator *rep = connection->FindReplicator(message->targetID);
|
|
|
|
if (rep)
|
|
{
|
|
targetEntity.Add(Cast_Object(
|
|
Entity*,
|
|
rep
|
|
));
|
|
|
|
//
|
|
// If we have an entity we are locked on then targetPoint is the offset from the object itself
|
|
// we save this to use later in the raycast testing against where the object is now.
|
|
//
|
|
//
|
|
// Make targetOffset the difference from the target entity to the point
|
|
//
|
|
targetOffset.MultiplyByInverse(message->targetPoint, targetEntity.GetCurrent()->GetLocalToWorld());
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
targetPoint = message->targetPoint;
|
|
targetNormal = message->targetNormal;
|
|
damageAmount = message->damageAmount;
|
|
targetMaterial = message->targetMaterial;
|
|
heatAmount = message->heatAmount;
|
|
maxDistance = message->maxDistance;
|
|
// MSL 5.03 Min Distance
|
|
// minDistance = message->minDistance;
|
|
|
|
Check_Object(siteEntity.GetCurrent());
|
|
beamHitSFX = 0;
|
|
CommonConstructor();
|
|
|
|
lastParameterization = gos_GetElapsedTime();
|
|
// firstFrame = true;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
BeamEntity::CommonConstructor()
|
|
{
|
|
Check_Pointer(this);
|
|
|
|
rayCastDone = false;
|
|
lastParameterization = gos_GetElapsedTime();
|
|
|
|
if (siteEntity.GetCurrent())
|
|
{
|
|
ReplicatorID beam_hit_entity_id;
|
|
beam_hit_entity_id = MoveBeam();
|
|
//We want to make sure that what we are hitting now is what we thought we should hit..if not then no damage
|
|
if(targetEntity.GetCurrent())
|
|
{
|
|
//
|
|
// The hit effect will hang in empty space if we destroy something when we hit it. We should leave the destruction
|
|
// effect only in this case.
|
|
// This doesn't fix all cases since it could be destroyed as a result of another weapon
|
|
// this frame, and our hit effect will still be around.
|
|
//
|
|
|
|
//only damage if we are really hitting (nothing was in our way)
|
|
if(beam_hit_entity_id != ReplicatorID::Null)
|
|
InflictDamage(beam_hit_entity_id);
|
|
|
|
//
|
|
// Don't do hit effect under water unless we hit something
|
|
//
|
|
|
|
Check_Object (Map::GetInstance());
|
|
const Adept::Map__GameModel *mapModel = Map::GetInstance()->GetGameModel();
|
|
Check_Object(mapModel);
|
|
|
|
// if (!targetEntity.GetCurrent()->IsDestroyed())
|
|
// {
|
|
if (targetPoint.y >= ((mapModel->m_waterLevel) -.001f) ||
|
|
!targetEntity.GetCurrent()->IsDerivedFrom(Map::DefaultData))
|
|
{
|
|
CreateHitEffect();
|
|
PlaceDamageDecal();
|
|
}
|
|
// }
|
|
}
|
|
// else
|
|
// {
|
|
// MoveBeam();
|
|
// }
|
|
}
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
BeamEntity::PostCollisionExecute(Time till)
|
|
{
|
|
Check_Pointer(this);
|
|
|
|
Set_Statistic(Executed_Beam_Count, Executed_Beam_Count+1);
|
|
POSTCOLLISION_LOGIC("Beam");
|
|
|
|
#if 0
|
|
|
|
// NO LONGER SUPPORTED!!!!!!!!!!!!!
|
|
|
|
if(GetTimeParameter(till) >= 0.5)
|
|
{
|
|
//
|
|
//------------------------------
|
|
//We need to update our position
|
|
//------------------------------
|
|
//
|
|
Check_Object(siteEntity);
|
|
MWObject *mw_object = siteEntity->GetParentVehicle();
|
|
Check_Object(mw_object);
|
|
mw_object->targetQuery->line->FindEnd(&targetPoint);
|
|
targetEntity = mw_object->targetQuery->raySource;
|
|
|
|
lastParameterization = gos_GetElapsedTime();
|
|
|
|
MoveBeam();
|
|
|
|
if(targetEntity)
|
|
{
|
|
CreateHitEffect();
|
|
PlaceDamageDecal();
|
|
InflictDamage();
|
|
}
|
|
}
|
|
else
|
|
|
|
#endif
|
|
|
|
#if 0
|
|
if(firstFrame)
|
|
{
|
|
firstFrame = false;
|
|
RendererComponentWeb *video_web = GetComponentWeb(VideoRenderer::Instance);
|
|
if(video_web)
|
|
{
|
|
Check_Object(video_web);
|
|
video_web->SendCommand(Renderer::StartEffectCommandID);
|
|
}
|
|
}
|
|
#endif
|
|
MoveBeam();
|
|
|
|
SyncMatrices(true);
|
|
BaseClass::PostCollisionExecute(till);
|
|
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ReplicatorID
|
|
BeamEntity::MoveBeam()
|
|
{
|
|
Check_Object(this);
|
|
|
|
ReplicatorID hit_entity_id = ReplicatorID::Null;
|
|
|
|
// if we haven't lost our master...
|
|
if (siteEntity.GetCurrent() == NULL)
|
|
return hit_entity_id;
|
|
|
|
Check_Object(siteEntity.GetCurrent());
|
|
|
|
Point3D new_translation;
|
|
new_translation = siteEntity.GetCurrent()->GetLocalToWorld();
|
|
|
|
if (!rayCastDone && targetEntity.GetCurrent())
|
|
{
|
|
Stuff::LinearMatrix4D tempLtW;
|
|
// Stuff::LinearMatrix4D ltw = Stuff::LinearMatrix4D::Identity;
|
|
// ltw.BuildTranslation(targetOffset);
|
|
tempLtW = targetEntity.GetCurrent()->GetLocalToWorld();
|
|
targetPoint.Multiply(targetOffset, tempLtW);
|
|
hit_entity_id = targetEntity.GetCurrent()->GetReplicatorID();
|
|
}
|
|
|
|
Line3D target_line_copy;
|
|
Vector3D target_vector;
|
|
target_vector.Subtract(targetPoint, new_translation);
|
|
|
|
Scalar beam_length = target_vector.GetLength();
|
|
beamDistanceAttribute = beam_length;
|
|
|
|
if(!rayCastDone)
|
|
{
|
|
rayCastDone = true;
|
|
Line3D target_line;
|
|
Normal3D target_normal;
|
|
|
|
target_line.SetOrigin(new_translation);
|
|
target_line.SetDirection(target_vector);
|
|
target_line.m_length = maxDistance;
|
|
|
|
|
|
Entity::CollisionQuery target_query(&target_line, &target_normal, (Entity::WalkerMask), inflictingVehicle);
|
|
Adept::Entity *entity_hit;
|
|
Check_Object(CollisionGrid::Instance);
|
|
entity_hit = CollisionGrid::Instance->ProjectLine(&target_query);
|
|
|
|
target_line_copy = *(target_query.m_line);
|
|
//
|
|
// If we don't hit anything with the cast, then we just leave the target point where it was last frame
|
|
//
|
|
// Not doing this check can cause a crash. If the beam goes through the "hit" object and the beam is pointed
|
|
// towards the end of the world, the m_line is extending off the map, and fails the FindZone() call.
|
|
//
|
|
if (entity_hit)
|
|
{
|
|
target_query.m_line->FindEnd(&targetPoint);
|
|
hit_entity_id = entity_hit->GetReplicatorID();
|
|
targetEntity.Remove();
|
|
targetEntity.Add(entity_hit);
|
|
}
|
|
|
|
PlayWaterEffectIfNecessary(target_line_copy);
|
|
}
|
|
|
|
LinearMatrix4D new_position = LinearMatrix4D::Identity;
|
|
new_position.BuildTranslation(new_translation);
|
|
|
|
ElementRenderer::Element *element = GetElement();
|
|
Check_Object(element);
|
|
element->SetLocalToParent(new_position);
|
|
NeedMatrixSync();
|
|
|
|
return hit_entity_id;
|
|
|
|
|
|
#if 0
|
|
LinearMatrix4D new_position;
|
|
Point3D new_translation;
|
|
|
|
new_translation = siteEntity->GetLocalToWorld();
|
|
new_position.BuildTranslation(new_translation);
|
|
|
|
Vector3D target_vector;
|
|
target_vector.Subtract(targetPoint, new_translation);
|
|
Scalar beam_length = target_vector.GetLength();
|
|
|
|
if(beam_length > maxDistance)
|
|
{
|
|
//
|
|
//----------
|
|
//Scale Beam
|
|
//----------
|
|
//
|
|
Scalar scale;
|
|
scale = maxDistance / beam_length;
|
|
target_vector *= scale;
|
|
}
|
|
|
|
YawPitchRange new_rotation;
|
|
new_rotation = target_vector;
|
|
YawPitchRoll new_yaw_pitch_roll = YawPitchRoll::Identity;
|
|
new_yaw_pitch_roll.yaw = new_rotation.yaw;
|
|
new_yaw_pitch_roll.pitch = new_rotation.pitch;
|
|
beamDistanceAttribute = new_rotation.range;
|
|
new_position.BuildRotation(new_yaw_pitch_roll);
|
|
|
|
ElementRenderer::Element *element = GetElement();
|
|
Check_Object(element);
|
|
element->SetLocalToParent(new_position);
|
|
NeedMatrixSync();
|
|
#endif
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void
|
|
BeamEntity::PlayWaterEffectIfNecessary(Line3D target_Line)
|
|
{
|
|
const GameModel * model = GetGameModel();
|
|
Check_Object(model);
|
|
Check_Object (Map::GetInstance());
|
|
const Adept::Map__GameModel *mapModel = Map::GetInstance()->GetGameModel();
|
|
Check_Object(mapModel);
|
|
|
|
//
|
|
// Because of certain assumptions at the lower level if you put in watersurface
|
|
// then you end up trying to collision when you get added to the zone, and that's
|
|
// a bad thing if you don't have a collision volume
|
|
//
|
|
|
|
// if (model->waterSurface)
|
|
// {
|
|
Stuff::Scalar product;
|
|
Plane water_Level;
|
|
water_Level.normal.x = 0.0f;
|
|
water_Level.normal.y = 1.0f;
|
|
water_Level.normal.z = 0.0f;
|
|
water_Level.offset = mapModel->m_waterLevel;
|
|
|
|
Stuff::Scalar to_water = target_Line.GetDistanceTo(water_Level, &product);
|
|
if (product<0.0f && to_water>=0.0f && to_water<=target_Line.m_length)
|
|
{
|
|
Line3D target_LineWaterIntersection;
|
|
target_LineWaterIntersection = target_Line;
|
|
|
|
target_LineWaterIntersection.m_length = to_water;
|
|
|
|
Point3D point_in_world;
|
|
target_LineWaterIntersection.FindEnd(&point_in_world);
|
|
|
|
//
|
|
// Make sure we didn't hit a plane off the map
|
|
//
|
|
if (Map::GetInstance()->FindZone(point_in_world) != -1)
|
|
{
|
|
|
|
ResourceID hit_effect_resource_id = ResourceID::Null;
|
|
|
|
if(model->hitEffectMaterialTable != ResourceID::Null)
|
|
{
|
|
Entity__GameModel::GetEffectResourceID(&hit_effect_resource_id,
|
|
model->hitEffectMaterialTable, WaterMaterial
|
|
);
|
|
}
|
|
// else
|
|
//{
|
|
// hit_effect_resource_id = model->hitEffectResourceID;
|
|
// }
|
|
|
|
if(hit_effect_resource_id != ResourceID::Null)
|
|
{
|
|
Resource hit_effect_resource(hit_effect_resource_id);
|
|
Verify(hit_effect_resource.DoesResourceExist());
|
|
|
|
ClassID class_ID;
|
|
class_ID = GetClassIDFromDataListID(hit_effect_resource_id);
|
|
Verify(class_ID != NullClassID);
|
|
|
|
LinearMatrix4D effect_position = LinearMatrix4D::Identity;
|
|
effect_position.AlignLocalAxisToWorldVector(water_Level.normal, Y_Axis, X_Axis, Z_Axis);
|
|
effect_position.BuildTranslation(point_in_world);
|
|
|
|
Effect::CreateMessage effect_create_message(
|
|
sizeof(Effect::CreateMessage),
|
|
DefaultEventPriority,
|
|
CreateMessage::DefaultFlags,
|
|
class_ID,
|
|
Effect::DefaultFlags,
|
|
hit_effect_resource_id,
|
|
effect_position,
|
|
0.0f,
|
|
ExecutionStateEngine::AlwaysExecuteState,
|
|
NameTable::NullObjectID,
|
|
Entity::DefaultAlignment
|
|
);
|
|
MemoryStream stream(&effect_create_message, effect_create_message.messageLength);
|
|
|
|
Entity *entity;
|
|
ReplicatorID beam_id = Connection::Hermit->GetNextReplicatorID();
|
|
entity = CreateEntity(&stream, &beam_id, false);
|
|
|
|
#ifdef HUNT_ADD_EFFECT_BUG
|
|
|
|
if (entity == NULL)
|
|
{
|
|
STOP(("FAILED CREATE ENTITY BEAM"));
|
|
}
|
|
|
|
#endif
|
|
|
|
Check_Object(entity);
|
|
Check_Object(Map::GetInstance());
|
|
Map::GetInstance()->AddChild(entity);
|
|
entity->SyncMatrices(true);
|
|
|
|
// play SFX
|
|
beamHitSFX = 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
// }
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
BeamEntity::CreateHitEffect()
|
|
{
|
|
Check_Object(this);
|
|
|
|
const GameModel *model = GetGameModel();
|
|
Check_Object(model);
|
|
|
|
ResourceID hit_effect_resource_id = ResourceID::Null;
|
|
|
|
if((model->hitEffectMaterialTable != ResourceID::Null) &&
|
|
(targetMaterial >= 0) && (targetMaterial < MaterialCount))
|
|
{
|
|
Entity__GameModel::GetEffectResourceID(&hit_effect_resource_id,
|
|
model->hitEffectMaterialTable, targetMaterial
|
|
);
|
|
}
|
|
else
|
|
{
|
|
hit_effect_resource_id = model->hitEffectResourceID;
|
|
}
|
|
|
|
if(hit_effect_resource_id != ResourceID::Null)
|
|
{
|
|
Resource hit_effect_resource(hit_effect_resource_id);
|
|
Verify(hit_effect_resource.DoesResourceExist());
|
|
|
|
ClassID class_ID;
|
|
class_ID = GetClassIDFromDataListID(hit_effect_resource_id);
|
|
Verify(class_ID != NullClassID);
|
|
|
|
LinearMatrix4D effect_position = LinearMatrix4D::Identity;
|
|
effect_position.AlignLocalAxisToWorldVector(targetNormal, Y_Axis, X_Axis, Z_Axis);
|
|
effect_position.BuildTranslation(targetPoint);
|
|
|
|
Effect::CreateMessage effect_create_message(
|
|
sizeof(Effect::CreateMessage),
|
|
DefaultEventPriority,
|
|
CreateMessage::DefaultFlags,
|
|
class_ID,
|
|
Effect::DefaultFlags,
|
|
hit_effect_resource_id,
|
|
effect_position,
|
|
0.0f,
|
|
ExecutionStateEngine::AlwaysExecuteState,
|
|
NameTable::NullObjectID,
|
|
Entity::DefaultAlignment
|
|
);
|
|
MemoryStream stream(&effect_create_message, effect_create_message.messageLength);
|
|
|
|
Entity *entity;
|
|
ReplicatorID beam_id = Connection::Hermit->GetNextReplicatorID();
|
|
entity = CreateEntity(&stream, &beam_id, false);
|
|
|
|
#ifdef HUNT_ADD_EFFECT_BUG
|
|
|
|
if (entity == NULL)
|
|
{
|
|
STOP(("FAILED CREATE ENTITY BEAM"));
|
|
}
|
|
|
|
#endif
|
|
|
|
Check_Object(entity);
|
|
Check_Object(Map::GetInstance());
|
|
Map::GetInstance()->AddChild(entity);
|
|
entity->SyncMatrices(true);
|
|
|
|
// play SFX
|
|
beamHitSFX = 1;
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
BeamEntity::PlaceDamageDecal()
|
|
{
|
|
Check_Object(this);
|
|
|
|
const GameModel *model = GetGameModel();
|
|
Check_Object(model);
|
|
if (model->damageDecalResourceID != ResourceID::Null)
|
|
{
|
|
Resource damage_effect_resource(model->damageDecalResourceID);
|
|
Verify(damage_effect_resource.DoesResourceExist());
|
|
ClassID class_ID;
|
|
class_ID = GetClassIDFromDataListID(model->damageDecalResourceID);
|
|
Verify(class_ID != NullClassID);
|
|
|
|
LinearMatrix4D effect_position = LinearMatrix4D::Identity;
|
|
effect_position.AlignLocalAxisToWorldVector(targetNormal, Y_Axis, X_Axis, Z_Axis);
|
|
effect_position.BuildTranslation(targetPoint);
|
|
|
|
Decal::CreateMessage decal_create_message(
|
|
sizeof(Effect::CreateMessage),
|
|
DefaultEventPriority,
|
|
CreateMessage::DefaultFlags,
|
|
class_ID,
|
|
Decal::DefaultFlags,
|
|
model->damageDecalResourceID,
|
|
effect_position,
|
|
0.0f,
|
|
ExecutionStateEngine::NeverExecuteState,
|
|
NameTable::NullObjectID,
|
|
Entity::DefaultAlignment
|
|
);
|
|
MemoryStream stream(&decal_create_message, decal_create_message.messageLength);
|
|
|
|
Entity *entity;
|
|
ReplicatorID beam_id = Connection::Hermit->GetNextReplicatorID();
|
|
entity = CreateEntity(&stream, &beam_id, false);
|
|
Check_Object(entity);
|
|
Check_Object(targetEntity.GetCurrent());
|
|
targetEntity.GetCurrent()->AddChild(entity);
|
|
entity->SyncMatrices(true);
|
|
}
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
BeamEntity::InflictDamage(ReplicatorID damaged_entity)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(targetEntity.GetCurrent());
|
|
Check_Object(siteEntity.GetCurrent());
|
|
|
|
// MSL 5.06 Armor Mode
|
|
MWApplication *m_App;
|
|
m_App = MWApplication::GetInstance ();
|
|
m_ArmorMode = m_App->GetLocalNetParams()->m_armormodeOn;
|
|
|
|
Entity::TakeDamageMessage damage_message(
|
|
//targetEntity.GetCurrent()->GetReplicatorID(),
|
|
damaged_entity,
|
|
inflictingEntityID,
|
|
damageAmount,
|
|
m_ArmorMode,
|
|
BeamDamageType,
|
|
targetNormal,
|
|
targetPoint,
|
|
heatAmount,
|
|
false,
|
|
itemID
|
|
);
|
|
|
|
targetEntity.GetCurrent()->Receive(&damage_message);
|
|
|
|
//targetEntity->Dispatch(&damage_message);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
BeamEntity::TestInstance() const
|
|
{
|
|
Verify(IsDerivedFrom(DefaultData));
|
|
}
|
|
|