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

210 lines
4.5 KiB
C++

#include "MW4Headers.hpp"
#include "AI_FireData.hpp"
#include <Adept\CollisionGrid.hpp>
#include <Adept\Map.hpp>
#include "MWMover.hpp"
#include "aiutils.hpp"
#include "Weapon.hpp"
#include "ProjectileWeapon.hpp"
#include "Vehicle.hpp"
#include "MWDamageObject.hpp"
#include <Adept\Entity.hpp>
#include <Adept\Site.hpp>
using namespace MW4AI;
using namespace Stuff;
extern __int64 tCombatAITime_RayCasting;
extern __int64 tRayCasting;
Stuff::Scalar ground_hit_fudge_distance = 20.0f;
// TODO: how to ensure that our lifetime is longer than the source? refcounting? will it be an issue?
FireData::FireData(Adept::Entity& source,
const Stuff::Point3D& src,
const Stuff::Point3D& dest)
: m_Query(&m_Line,&m_Normal,Adept::Entity::CanBeShotFlag,&source)
, m_Normal(1,0,0)
, m_Source(source)
{
Check_Object(&source);
CreateLine(src,dest);
}
FireData::FireData(Adept::Entity& source,
MechWarrior4::Weapon& weapon,
const Stuff::Point3D& dest)
: m_Query(&m_Line,&m_Normal,Adept::Entity::CanBeShotFlag,&source)
, m_Normal(1,0,0)
, m_Source(source)
{
Check_Object(&source);
Stuff::Point3D src;
if (weapon.sitePointer == 0)
{
src = weapon.GetParentVehicle()->GetLocalToWorld();
}
else
{
src = weapon.sitePointer->GetLocalToWorld();
}
CreateLine(src,dest);
}
void FireData::CreateLine(const Stuff::Point3D& src,
const Stuff::Point3D& dest)
{
Vector3D target_direction;
target_direction.Subtract(dest,src);
m_Line.SetOrigin(src);
if (Small_Enough(target_direction))
{
m_Line.SetDirection(UnitVector3D(1,0,0));
m_Line.m_length = 0;
}
else
{
UnitVector3D origin_direction;
if (target_direction.GetLengthSquared() == 0)
{
target_direction = Stuff::Point3D(1,0,0);
}
origin_direction.Normalize(target_direction);
m_Line.SetDirection(origin_direction);
m_Line.m_length = target_direction.GetLength();
}
}
FireData::FireData(const FireData& copy_from)
: m_Query(copy_from.m_Query)
, m_Normal(copy_from.m_Normal)
, m_Line(copy_from.m_Line)
, m_Source(copy_from.m_Source)
{
m_Query.m_line = &m_Line;
m_Query.m_normal = &m_Normal;
}
Adept::Entity* FireData::Project()
{
if ((Small_Enough(m_Line.m_length)) ||
(Small_Enough(m_Line.m_direction)))
{
return (0);
}
Adept::Entity *entity_hit;
Check_Object(CollisionGrid::Instance);
{
TIME_FUNCTION(tCombatAITime_RayCasting);
TIME_FUNCTION(tRayCasting);
entity_hit = CollisionGrid::Instance->ProjectLine(&m_Query);
}
m_Query.m_raySource = entity_hit;
return (entity_hit);
}
FireData::HIT_RESULT FireData::GetHitResult(Adept::Entity* desired_target, bool ignore_dead_components) const
{
Verify(Adept::Map::GetInstance() != 0);
if (desired_target == 0)
{
if ((m_Query.m_raySource == 0) ||
(m_Query.m_raySource == Adept::Map::GetInstance()))
{
return (HIT_TARGET);
}
return (HIT_SOMETHING_ELSE);
}
Check_Object(desired_target);
if (m_Query.m_raySource == 0)
{
return (HIT_NOTHING);
}
if ((m_Query.m_raySource == Adept::Map::GetInstance()) &&
(m_Query.m_line != 0))
{
if (m_Query.m_line->m_length + ground_hit_fudge_distance > GetApproximateLength(GetOrigin(),(Stuff::Point3D)desired_target->GetLocalToWorld()))
{
return (HIT_NOTHING);
}
return (HIT_SOMETHING_ELSE);
}
if (m_Query.m_raySource->IsDerivedFrom(MWMover::DefaultData) == false)
{
if (m_Query.m_raySource == desired_target)
{
return (HIT_TARGET);
}
return (HIT_SOMETHING_ELSE);
}
MechWarrior4::MWMover* mover = Cast_Object(MechWarrior4::MWMover*,m_Query.m_raySource);
Check_Object(mover);
if (mover == desired_target)
{
return (HIT_TARGET);
}
if (ignore_dead_components == false)
{
if ((mover->damageObject != 0) &&
(mover->damageObject->internalDamageObject != 0) &&
(mover->damageObject->internalDamageObject->GetCurrentDamageLevel() == Adept::InternalDamageObject::Destroyed))
{
return (HIT_NOTHING);
}
}
if (mover->GetParentVehicle() == 0)
{
return (HIT_NOTHING);
}
if ((mover->GetParentVehicle() == desired_target) ||
(mover->GetParentVehicle()->GetAlignment() != m_Source.GetAlignment()))
{
return (HIT_TARGET);
}
return (HIT_SOMETHING_ELSE);
}
bool FireData::HitsGround() const
{
if ((m_Query.m_raySource != 0) &&
(m_Query.m_raySource == Adept::Map::GetInstance()) &&
(m_Query.m_line != 0))
{
return (true);
}
return (false);
}