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

580 lines
12 KiB
C++

#include "MW4Headers.hpp"
#include "AI_CombatTacticInterface.hpp"
#include "AI_Weapons.hpp"
#include "Mech.hpp"
#include "MWMission.hpp"
#include "Airplane.hpp"
#include "AI_FireStyle.hpp"
#include "AI_Tactics.hpp"
#include "Mech.hpp"
#include "JumpJet.hpp"
#include "AI_Groups.hpp"
#include "AI_Damage.hpp"
#include "ShooterAI.hpp"
using namespace MW4AI;
extern __int64 tCombatAITime_ShotWithin;
bool CombatTacticInterface::g_DisableMovement = false;
bool CombatTacticInterface::g_DisableFiring = false;
const Stuff::Scalar min_move_reissuance_distance = 8.0f;
CombatTacticInterface::CombatTacticInterface(MechWarrior4::CombatAI& combat_ai)
: m_CombatAI(combat_ai)
, m_LastMoveDestScore(0)
{
}
void CombatTacticInterface::MoveTo(const Point3D& point, bool move_forward, bool throttle_override, MWObject* ram_target)
{
#ifdef LAB_ONLY
if (ram_target == 0)
{
Verify(PointIsValid(point,true));
}
if (g_DisableMovement == true)
{
Stop();
return;
}
#endif
// TODO: move this somewhere else; also take move_forward and throttle_override into account
if ((m_CombatAI.m_TimeNotMoving == 0) &&
(GetLengthSquared(m_CombatAI.m_LastMoveDest,point) < (min_move_reissuance_distance * min_move_reissuance_distance)))
{
return;
}
m_CombatAI.MoveToPoint(point,move_forward,throttle_override,ram_target);
m_LastMoveDestScore = 0;
}
Stuff::Point3D CombatTacticInterface::GetAimPoint() const
{
return (m_CombatAI.m_LastAimPoint);
}
void CombatTacticInterface::TrackTo(const Stuff::Point3D& point)
{
m_CombatAI.TrackToPoint(point);
}
void CombatTacticInterface::TurnTo(const Stuff::Point3D& point, bool must_be_torso_twisted)
{
m_CombatAI.TurnToPoint(point,must_be_torso_twisted);
}
void CombatTacticInterface::PitchTo(const Stuff::Point3D& point)
{
m_CombatAI.PitchToPoint(point);
}
void CombatTacticInterface::Stop()
{
m_CombatAI.StopMoving();
m_LastMoveDestScore = 0;
}
void CombatTacticInterface::Fire(FireStyles::FireStyleID style_id)
{
#ifdef LAB_ONLY
if (g_DisableFiring == true)
{
return;
}
#endif
m_CombatAI.TryToFire(style_id);
}
bool CombatTacticInterface::HasPath() const
{
if (m_CombatAI.m_CurPath != 0)
{
return (true);
}
return (false);
}
bool CombatTacticInterface::Moving() const
{
return (m_CombatAI.m_TimeNotMoving == 0);
}
Stuff::Scalar CombatTacticInterface::WeaponRange(WR_WHO who, WR_QUALIFIER qualifier) const
{
MWObject* x = 0;
if (who == TacticInterface::SELF)
{
x = &(m_CombatAI.GetSelf());
}
else
{
x = &(m_CombatAI.GetTarget());
}
if (qualifier == TacticInterface::MIN)
{
return (GetMinWeaponDistance(*x));
}
return (GetMaxWeaponDistance(*x));
}
bool CombatTacticInterface::PointIsValid(const Point3D& point, bool ignore_mission_bounds, bool ignore_squads) const
{
return (m_CombatAI.PointIsValid(point,ignore_mission_bounds,ignore_squads));
}
MechWarrior4::MWObject& CombatTacticInterface::GetSelf() const
{
return (m_CombatAI.GetSelf());
}
MechWarrior4::Vehicle* CombatTacticInterface::GetSelf_AsVehicle() const
{
return (m_CombatAI.GetSelf_AsVehicle());
}
MechWarrior4::MWObject& CombatTacticInterface::GetTarget() const
{
return (m_CombatAI.GetTarget());
}
MechWarrior4::Vehicle* CombatTacticInterface::GetTarget_AsVehicle() const
{
return (m_CombatAI.GetTarget_AsVehicle());
}
FireData::HIT_RESULT CombatTacticInterface::GetLastHitResult() const
{
return (m_CombatAI.m_HitResult);
}
Stuff::Scalar CombatTacticInterface::GetDistanceFromTargetSquared() const
{
return (m_CombatAI.m_DistanceFromTargetSquared);
}
Moods::ID CombatTacticInterface::GetMood() const
{
int current_mood = (int)m_CombatAI.CurrentMood();
return ((Moods::ID)current_mood);
}
Stuff::Scalar CombatTacticInterface::GetDistanceFromDestinationSquared() const
{
if ((m_CombatAI.m_CurMove == 0) ||
(m_CombatAI.m_CurMove->Done() == true))
{
return (0);
}
if (m_CombatAI.m_LastMoveDest.GetLengthSquared() == 0)
{
return (0);
}
Stuff::Vector3D delta;
delta.Subtract((Stuff::Point3D)m_CombatAI.GetSelf().GetLocalToWorld(),
m_CombatAI.m_LastMoveDest);
return (delta.GetLengthSquared());
}
bool CombatTacticInterface::GetLastMoveDest(Stuff::Point3D& dest, bool ignore_movement) const
{
if (ignore_movement == false)
{
if ((m_CombatAI.m_CurMove == 0) ||
(m_CombatAI.m_CurMove->Done() == true))
{
return (false);
}
}
dest = m_CombatAI.m_LastMoveDest;
return (true);
}
void CombatTacticInterface::ClearMoveOrder()
{
m_CombatAI.ClearMoveOrder();
m_LastMoveDestScore = 0;
}
bool CombatTacticInterface::ProjectileApproaching(Stuff::Scalar interval)
{
const Stuff::Scalar min_reaction_delay = 0.2f;
Verify(interval > min_reaction_delay);
if ((m_CombatAI.m_LastTimeProjectileShotAtMe == 0) ||
(gos_GetElapsedTime() < m_CombatAI.m_LastTimeProjectileShotAtMe + min_reaction_delay))
{
return (false);
}
return (gos_GetElapsedTime() < m_CombatAI.m_LastTimeProjectileShotAtMe + interval);
}
const Stuff::Point3D& CombatTacticInterface::GetProjectileOrigin()
{
return (m_CombatAI.m_LastProjectileOrigin);
}
void CombatTacticInterface::Stand()
{
if (m_CombatAI.GetSelf_AsVehicle() == 0)
{
return;
}
if (m_CombatAI.GetSelf_AsVehicle()->IsDerivedFrom(Mech::DefaultData) == true)
{
Mech* mech = Cast_Object(Mech*,m_CombatAI.GetSelf_AsVehicle());
mech->GetUpRequestRequest();
}
}
void CombatTacticInterface::Crouch()
{
m_CombatAI.Crouch();
}
bool CombatTacticInterface::Crouching() const
{
return (m_CombatAI.Crouching());
}
void CombatTacticInterface::ThrottleOverride(Stuff::Scalar duration, bool force)
{
m_CombatAI.ThrottleOverride(duration,force);
}
bool CombatTacticInterface::ShotWithin(Stuff::Scalar lastvalid) const
{
TIME_FUNCTION(tCombatAITime_ShotWithin);
if (m_CombatAI.ShotBy(gos_GetElapsedTime() - lastvalid) != 0)
{
return (true);
}
return (false);
}
bool CombatTacticInterface::FiredWithin(Stuff::Scalar lastvalid) const
{
if (gos_GetElapsedTime() < m_CombatAI.GetLastFiredTime() + lastvalid)
{
return (true);
}
return (false);
}
void CombatTacticInterface::Jump()
{
if (CanJump() == false)
{
return;
}
m_CombatAI.OrderJump();
}
void CombatTacticInterface::Jump(Stuff::Scalar duration)
{
if (CanJump() == false)
{
return;
}
m_CombatAI.OrderJump(duration);
}
void CombatTacticInterface::StopJumping()
{
m_CombatAI.OrderStopJumping();
}
bool CombatTacticInterface::GetUnableToFireDuration(Stuff::Scalar duration) const
{
return (m_CombatAI.GetUnableToFireDuration(duration));
}
bool CombatTacticInterface::ShouldForceDestinationRecalc() const
{
return (m_CombatAI.ShouldForceDestinationRecalc());
}
MechWarrior4::MWObject* CombatTacticInterface::GetNearest(bool fMustBeEnemy)
{
return (m_CombatAI.GetNearest(fMustBeEnemy));
}
int CombatTacticInterface::GetEliteLevel() const
{
return (m_CombatAI.EliteSkill());
}
Stuff::Scalar CombatTacticInterface::GetTimeTargetedByEnemy() const
{
return (m_CombatAI.GetTimeTargetedByEnemy());
}
Stuff::Scalar CombatTacticInterface::GetAttackThrottle() const
{
return (m_CombatAI.GetAttackThrottle());
}
void CombatTacticInterface::ForceDestinationRecalc()
{
m_CombatAI.ForceDestinationRecalc();
}
Stuff::Point3D CombatTacticInterface::GetMoveDest() const
{
return (m_CombatAI.GetMoveDest());
}
Stuff::Scalar CombatTacticInterface::GetLastTimeRammedTarget() const
{
return (m_CombatAI.GetLastTimeRammedTarget());
}
Stuff::Scalar CombatTacticInterface::GetLastTimeJumped() const
{
return (m_CombatAI.GetLastTimeJumped());
}
Stuff::LinearMatrix4D CombatTacticInterface::GetAttackOrderPosition() const
{
if (m_CombatAI.m_LastAttackOrderPosition.GetPointer() == 0)
{
return (m_CombatAI.GetSelf().GetLocalToWorld());
}
return (*(m_CombatAI.m_LastAttackOrderPosition));
}
bool CombatTacticInterface::GetEscapeRegionFocusIfAvailable(Stuff::Point3D& focus) const
{
return (m_CombatAI.GetEscapeRegionFocusIfAvailable(focus));
}
void CombatTacticInterface::SurrenderPose()
{
m_CombatAI.SurrenderPose();
}
void CombatTacticInterface::SetSpeed(Stuff::Scalar speed)
{
m_CombatAI.SetSpeed(speed);
}
bool CombatTacticInterface::SuicideIsOK() const
{
return (m_CombatAI.SuicideIsOK());
}
unsigned int CombatTacticInterface::NumLegsDestroyed() const
{
return (m_CombatAI.m_NumLegsBlownOff);
}
Stuff::Scalar CombatTacticInterface::GetMovementScore() const
{
return (m_LastMoveDestScore);
}
void CombatTacticInterface::SetMovementScore(Stuff::Scalar score)
{
m_LastMoveDestScore = score;
}
bool CombatTacticInterface::PointIsInBadNeighborhood(const Stuff::Point3D& point) const
{
return (m_CombatAI.PointIsInBadNeighborhood(point));
}
bool CombatTacticInterface::ShouldRun() const
{
if (m_CombatAI.m_PerWeaponRayCasting == true)
{
return (true);
}
return (m_CombatAI.ShouldRun(true));
}
Stuff::Scalar CombatTacticInterface::GetCombatRadiusForRange(Stuff::Scalar percentile_range)
{
return (m_CombatAI.GetCombatRadiusForRange(percentile_range));
}
Stuff::LinearMatrix4D CombatTacticInterface::GetLastMoveOrderPosition() const
{
if (m_CombatAI.m_LastMoveOrderPosition.GetPointer() == 0)
{
return (m_CombatAI.GetSelf().GetLocalToWorld());
}
return (*(m_CombatAI.m_LastMoveOrderPosition));
}
Stuff::Scalar CombatTacticInterface::GetNormalizedJumpJetFuel()
{
if (GetSelf().IsDerivedFrom(Mech::DefaultData) == false)
{
return (0);
}
Mech* mech = Cast_Object(Mech*,&(GetSelf()));
Check_Object(mech);
if ((mech->GetJumpJet() == 0) ||
(mech->GetJumpJet()->GetGameModel() == 0) ||
(mech->GetJumpJet()->GetGameModel()->m_burnTime <= 0))
{
return (0);
}
return (mech->GetJumpJet()->CurrentCharge() / mech->GetJumpJet()->GetGameModel()->m_burnTime);
}
bool CombatTacticInterface::CanRetreat() const
{
std::vector<MWObject*> lancemates;
Groups::GetLancemates(lancemates);
if (std::find(lancemates.begin(),lancemates.end(),&(GetSelf())) != lancemates.end())
{
return (false);
}
return (true);
}
Stuff::Scalar CombatTacticInterface::GetCurrentVulnerableComponent()
{
return (m_CombatAI.GetCurrentVulnerableComponent());
}
bool CombatTacticInterface::CanJump() const
{
if (GetSelf().IsDerivedFrom(Mech::DefaultData) == false)
{
return (false);
}
Mech* mech = Cast_Object(Mech*,&GetSelf());
if ((mech->GetJumpJet() == 0) ||
(mech->GetJumpJet()->IsDestroyed() == true))
{
return (false);
}
return (true);
}
bool CombatTacticInterface::CanCrouch() const
{
return (GetSelf().IsDerivedFrom(Mech::DefaultData));
}
void CombatTacticInterface::FloatToPoint(const Stuff::Point3D& point)
{
m_CombatAI.FloatToPoint(point);
}
bool CombatTacticInterface::IsShootOnlyAI() const
{
return (m_CombatAI.IsDerivedFrom(ShooterAI::DefaultData));
}
void CombatTacticInterface::SetFallDampingEnabled(bool enabled)
{
m_CombatAI.SetFallDampingEnabled(enabled);
}
Adept::ObjectID CombatTacticInterface::GetObjectID() const
{
return (m_CombatAI.GetSelf().objectID);
}
Stuff::Scalar CombatTacticInterface::GetMaxFireCheatAngle() const
{
return (m_CombatAI.GetMaxFireCheatAngle());
}
bool CombatTacticInterface::LineMightHitFriendlyUnits(const Stuff::Line3D& line) const
{
return (m_CombatAI.LineMightHitFriendlyUnits(line));
}
bool CombatTacticInterface::MovedWithin(Stuff::Scalar duration) const
{
return (m_CombatAI.MovedWithin(duration));
}
void CombatTacticInterface::ContinuousFlyBy(const Stuff::Point3D& loc)
{
m_CombatAI.ContinuousFlyBy(loc);
}
bool CombatTacticInterface::RecentPathsFailed() const
{
return (m_CombatAI.RecentPathsFailed());
}
bool CombatTacticInterface::CanMove() const
{
return (m_CombatAI.CanMove());
}
bool CombatTacticInterface::MoveRequestPending() const
{
return (m_CombatAI.MoveRequestPending());
}
bool CombatTacticInterface::CanTrack() const
{
return (m_CombatAI.CanTrack());
}
bool CombatTacticInterface::CanTurn() const
{
return (m_CombatAI.CanTurn());
}
Stuff::Scalar CombatTacticInterface::DamageTakenSinceAttackOrder() const
{
Stuff::Scalar damage = MW4AI::Damage::GetDamageRating(m_CombatAI.GetSelf());
return (Stuff::Fabs(damage - m_CombatAI.m_LastAttackOrderDamageRating));
}
Stuff::Point3D CombatTacticInterface::GetLeashCenter() const
{
return (m_CombatAI.m_CombatLeash);
}
Stuff::Scalar CombatTacticInterface::GetLeashRadius() const
{
return (m_CombatAI.m_CombatLeashRadius);
}