Files
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

1051 lines
27 KiB
C++

//===========================================================================//
// File: CombatAI.hpp //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 09/21/99 PDT Created File //
// Question: why is this even here when we have SourceSafe? ... //
//---------------------------------------------------------------------------//
// Copyright (C) 1999, Microsoft //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#pragma once
#ifndef COMBATAI_HPP
#define COMBATAI_HPP
#include "MoverAI.hpp"
#include "AI_Tactics.hpp"
#include "AI_CombatTacticInterface.hpp"
#include "aiutils.hpp"
#include "AI_Weapons.hpp"
#include "Group.hpp"
#include "AI_SearchLight.hpp"
#pragma warning(push)
#include <stlport\list>
#pragma warning(pop)
#include "AI_FireParamPackage.hpp"
#include "NetWeapon.hpp"
#include "AI_SquadOrders.hpp"
#include "torso.hpp"
namespace std
{
template <class T> class vector;
};
namespace MW4AI
{
namespace FireStyles
{
class FireStyle;
};
class FireParamPackage;
extern HGOSHEAP g_CombatAIHeap;
};
namespace Adept
{
class DamageObject;
};
namespace MechWarrior4
{
class MWObject;
typedef MoverAI__CreateMessage CombatAI__CreateMessage;
//##########################################################################
//########################### CombatAI ################################
//##########################################################################
class CombatAI
: public MoverAI
{
typedef MoverAI inherited;
friend class MW4AI::CombatTacticInterface;
public:
static void InitializeClass();
static void TerminateClass();
static ClassData *DefaultData;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Tactics
//
enum AttackState
{
ATTACKING = true,
NOT_ATTACKING = false
};
inline AttackState GetAttackState() const;
inline MW4AI::TacticInterface& GetTacticInterface();
MWObject* GetNearest(bool fMustBeEnemy = false); // TODO: make this an enum or something ...
inline Stuff::Point3D GetMoveDest() const;
bool ReactToCollision(Stuff::DynamicArrayOf<CollisionData> *collisions,bool& shoulddamage);
bool PointIsInBadNeighborhood(const Stuff::Point3D& point) const;
Stuff::Scalar GetCombatRadiusForRange(Stuff::Scalar percentile_range);
bool MovedWithin(Stuff::Scalar duration) const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
public:
typedef CombatAI__CreateMessage CreateMessage;
void TrackToPoint(const Stuff::Point3D& point);
void TurnToPoint(const Stuff::Point3D& point, bool must_be_torso_twisted = true);
void PitchToPoint(const Stuff::Point3D& point);
inline Stuff::Scalar GetTimeTargetedByFriendly() const;
virtual void Save (MemoryStream *stream);
virtual void Load (MemoryStream *stream);
virtual void NotifyRespawned();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Run-time Construction and Destruction Support
//
public:
static CombatAI* Make(CreateMessage *message,ReplicatorID *base_id); // FYI, this really should return an Auto_Ptr<>! -- PT
CombatAI(ClassData *class_data,
CreateMessage *message,
ReplicatorID *base_id,
ElementRenderer::Element *element);
~CombatAI();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Message Support
//
public:
enum
{
DebugTextMessageID = MechWarrior4::MoverAI::NextMessageID,
NextMessageID
};
void DebugTextMessageHandler(Adept::ReceiverDataMessageOf<int> *message);
protected:
static const MessageEntry MessageEntries[];
typedef std::vector<MWObject*> secondary_target_list;
virtual bool CanMove() const;
bool MoveRequestPending();
bool CanTurn();
bool CanTrack();
private:
class PatienceMonitor
{
public:
PatienceMonitor(int maximum);
bool Check();
void Notify(bool success);
private:
const int m_Maximum;
int m_Patience;
int m_Frustration;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Execution Support
//
public:
Stuff::Scalar m_LastTimeMoved;
protected:
Stuff::Auto_Ptr<MW4AI::Tactics::Tactic> m_Tactic;
Point3D m_LastPos;
Point3D m_LastMoveDest;
Point3D m_LastAimPoint;
MW4AI::CombatTacticInterface m_Interface;
MW4AI::FireData::HIT_RESULT m_HitResult;
Stuff::Scalar m_DistanceFromTargetSquared;
bool m_OverridingMovement;
Stuff::Scalar m_AttackThrottle;
Stuff::Scalar m_LastFireTime;
Stuff::Scalar m_MinFiringDelay;
Stuff::Scalar m_MaxFiringDelay;
Stuff::Scalar m_LastTimeProjectileShotAtMe;
Stuff::Point3D m_LastProjectileOrigin;
Stuff::Scalar m_ThrottleOverrideStopTime;
bool m_HoldingFire;
bool m_InternalArmorBreached;
bool m_LeftArmExists;
bool m_RightArmExists;
bool m_ForceDestinationRecalc;
char m_NumArmsBlownOff;
char m_NumLegsBlownOff;
Stuff::Scalar m_LastUnableToFireTime;
Stuff::Time m_LastFrameTime;
Stuff::Time m_ApproximateTimeBetweenFrames;
Stuff::Scalar m_LastFriendlyFireTime;
Stuff::Scalar m_FriendlyFireDelay;
Stuff::Scalar m_LastTimeTargeted;
Stuff::Scalar m_TimeBeingTargeted;
int m_LastTargetedAlignment;
Stuff::Scalar m_LastTimeRammedTarget;
Stuff::Scalar m_LastTimeJumped;
Stuff::Scalar m_JumpDuration;
bool m_PerformedFirstUpdate;
Stuff::Scalar m_SquadTargetingRadius;
Stuff::Point3D m_ExplicitFirePoint;
int m_ExplicitFireStretch;
Stuff::Auto_Ptr<Stuff::LinearMatrix4D> m_LastAttackOrderPosition;
Stuff::Auto_Ptr<Stuff::LinearMatrix4D> m_LastMoveOrderPosition;
bool m_WaitingForHeatToReachMinSkill;
std::vector<MW4AI::Tactics::TacticID> m_MostRecentTactics;
MW4AI::SearchLightController m_SearchLightController;
enum LookState
{
LOOK_LEFT,
LOOK_RIGHT,
LOOK_CENTER,
LOOK_BACK
// ,LOOK_UP,
// ,LOOK_DOWN
};
LookState m_LookState;
Stuff::Scalar m_LastLookTime;
Stuff::Scalar m_LastTimeLookChanged;
std::vector<Stuff::Point3D> m_BlockedMovePoints;
Stuff::Scalar m_AttackRadiusMultiplier;
Stuff::Point3D m_LastOffsetToMiss;
Stuff::Scalar m_MissOffsetStartTime;
Stuff::Scalar m_Last_Till_Value;
struct CanSeeResult
{
MW4AI::FireData::HIT_RESULT m_Result;
Adept::ObjectID m_Entity;
Stuff::Scalar m_Angle;
Stuff::Scalar m_Time;
};
std::vector<CanSeeResult> m_CanSeeResults;
Stuff::Auto_Ptr<MW4AI::SquadOrders> m_SquadOrders;
#ifdef LAB_ONLY
bool m_LastFireRejected;
#endif
Adept::ObjectID m_CheapShotTarget;
bool m_CheapShotShouldHit;
bool m_CheapShotShouldSpendAmmo;
bool m_PerWeaponRayCasting;
struct CachedTorsoRayCastFailure
{
Weapon* weapon;
Stuff::Scalar time;
};
std::list<CachedTorsoRayCastFailure> m_CachedTorsoRayCastFailures;
std::vector<Stuff::Scalar> m_MostRecentNoPathWarnings;
Stuff::Scalar m_LastTimeSwitchedTargets;
bool m_AutoTargetingEnabled;
Stuff::Scalar m_MinSpeed;
Stuff::Scalar m_GoalPitch;
Stuff::Scalar m_GoalYaw;
secondary_target_list m_SecondaryTargets;
Stuff::Time m_LastAttackIntervalRefresh;
Stuff::Scalar m_MinAttackInterval;
Stuff::Scalar m_MaxAttackInterval;
MW4AI::FireStyles::MaximumFire m_MaximumFire;
MW4AI::FireStyles::OpportunityFire m_OpportunityFire;
struct CachedFireSource
{
MW4AI::FireSource fire_source;
Adept::ObjectID object_id;
Stuff::Time last_update;
};
std::vector<CachedFireSource> m_FireSourceCache;
Stuff::Scalar m_CurrentVulnerableComponent;
PatienceMonitor m_FiringAttemptMonitor;
PatienceMonitor m_OpportunityFireMonitor;
Adept::ObjectID m_CachedNearest[2];
Stuff::Time m_CachedNearestTime[2];
std::vector<Weapon*> m_SavedWeapons;
Stuff::Time m_MoveRequestFinishedTime;
Stuff::Scalar m_LastAttackOrderDamageRating;
bool m_ShutDownDueToHeat;
bool m_IgnoreFog;
public:
bool OverridingMovement (void) const
{ return m_OverridingMovement; }
virtual void Shutdown() { inherited::Shutdown(); }
virtual void Startup() { inherited::Startup(); }
inline void EnablePerWeaponRayCasting(bool enable);
inline MW4AI::SearchLightController& GetSearchLightController();
void PreCollisionExecute(Stuff::Time till);
void PostCollisionExecute(Time till);
inline Stuff::Scalar GetLastFiredTime() const;
inline MWObject& GetSelf();
inline const MWObject& GetSelf() const;
inline Vehicle* GetSelf_AsVehicle();
inline const Vehicle* GetSelf_AsVehicle() const;
inline int GetNumArmsBlownOff() const;
inline int GetNumLegsBlownOff() const;
inline bool ShouldForceDestinationRecalc() const;
inline void ForceDestinationRecalc();
bool CanSee(MWObject& entity, Stuff::Scalar cheat_angle = Stuff::Pi_Over_4);
inline bool ShouldHoldFireToAvoidFriendlyFire() const;
inline Stuff::Scalar GetLastTimeRammedTarget() const;
inline Stuff::Scalar GetLastTimeJumped() const;
inline Stuff::Scalar GetSquadTargetingRadius() const;
inline void SetSquadTargetingRadius(Stuff::Scalar radius);
bool GetEscapeRegionFocusIfAvailable(Stuff::Point3D& focus) const;
inline void SetSquadOrders(Stuff::Auto_Ptr<MW4AI::SquadOrders>& orders);
inline MW4AI::SquadOrders* GetSquadOrders();
inline bool GetAutoTargeting() const;
inline void SetAutoTargeting(bool enabled);
inline bool GetIgnoreFog() const;
inline void SetIgnoreFog(bool ignore);
void FacePointOrLookOut(const Stuff::Point3D& point);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Order Support
//
void OrderAttack(bool fOverrideCurrentMove = true); // OrderAttack(): attack current target with "best" tactic, TBD by mech itself
void OrderAttackTactic(MW4AI::Tactics::TacticID tactic, bool fOverrideCurrentMove = true, bool is_explicit = true); // OrderAttackTactic(): attack current target with given tactic
void OrderShootPoint(const Stuff::Point3D& point, int stretch = 0);
void OrderStopAttacking(); // OrderStopAttacking(): stop attacking the current target
void OrderJump();
void OrderJump(Stuff::Scalar duration);
void OrderStopJumping();
void TrackOrTurnToPoint(const Point3D& point);
void Reset(bool reset_movement = true);
inline MW4AI::Tactics::TacticID GetCurrentTactic() const;
inline bool TacticIsFinished() const;
// void orderMoveLookOut (void);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Debug Stuff
//
void AddStatsToString(std::string& s);
void Info (void (*printCallback)(char* s));
void GetDirectPath(std::vector<Stuff::Point3D>& points);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Other Stuff
//
inline Stuff::Scalar GetAttackThrottle() const;
inline void SetAttackThrottle(Stuff::Scalar throttle);
inline Stuff::Scalar GetBaseChanceToHit() const;
inline void SetFiringDelay(Stuff::Scalar min, Stuff::Scalar max);
void ThrottleOverride(Stuff::Scalar duration, bool force = false);
void EnsureNotTargeting(Adept::ObjectID object);
Stuff::Scalar MaxVehicleSpeed();
void MoveToPoint(const Stuff::Point3D& point);
void FloatToPoint(const Stuff::Point3D& point);
bool PointIsValid(const Point3D& point, bool ignore_mission_bounds = false, bool ignore_squads = false) const;
void NotifyProjectileApproaching(const Stuff::Point3D& origin);
void NotifyShot(ObjectID who, bool fCanBeRecursive = true);
void NotifyShotFired(const Adept::Entity::CollisionQuery& query, MWObject& shooter);
void NotifyLastShotWasFriendlyFire(Adept::Entity& who_i_hit);
void NotifyInternalHit();
void NotifyComponentDestroyed(int zone);
void NotifyShutdown();
void NotifyAlignmentChanged();
void NotifyInTargetingReticule(MWObject& who);
void NotifyHeatShutdownImminent();
void NotifyFailedPilotingRoll();
void NotifyFriendlyFire(Adept::Entity& who_shot_me);
virtual void ContinuousFlyBy(const Stuff::Point3D& loc);
virtual bool GetExtendedSensorData(std::vector<MWObject*>& sensor_data_list);
virtual Stuff::Scalar GetLeastSquaredSensorDistance(const Stuff::Point3D& point) const;
inline bool GetHoldingFire() const;
inline void SetHoldingFire(bool hold_fire);
inline bool Attacking() const;
bool GetUnableToFireDuration(Stuff::Scalar within) const;
inline Stuff::Scalar GetAttackRadiusMultiplier() const;
void SetAttackRadiusMultiplier(Stuff::Scalar multiplier);
Stuff::Scalar GetMoodRadiusMultiplier() const;
void CenterTorso();
void SurrenderPose();
inline Stuff::Scalar GetCurrentVulnerableComponent() const;
inline void Execute_TurnToPoint(const Stuff::Point3D& point);
bool MoveDone() const;
void Crouch();
bool Crouching();
bool RecentPathsFailed() const;
MWObject* FindBestAutoTarget();
void SetMinSpeed(Stuff::Scalar min_speed);
void SetGoalPitch(Stuff::Scalar pitch);
void SetGoalYaw(Stuff::Scalar yaw);
protected:
bool GetIgnoringFriendlyFire() const;
void Update(Stuff::Time till);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Command Support
//
public:
enum
{
ATTACK_HIGHID = MoverAI::NextHighCommandID,
STOP_ATTACKING_HIGHID,
NextHighCommandID
};
enum
{
NOT_IMPLEMENTED_LOWID = MoverAI::NextLowCommandID,
NextLowCommandID
};
struct AimPoint
{
AimPoint() {};
AimPoint(const Stuff::Point3D& _aim_point,
Adept::Entity* _entity)
: aim_point(_aim_point)
, entity(_entity)
{
}
Stuff::Point3D aim_point;
Adept::Entity* entity;
};
inline Stuff::Scalar GetTimeTargetedByEnemy() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Command Implementation
//
private:
MW4AI::Tactics::TacticID SelectBestTactic() const;
inline MWObject& GetTarget();
inline Vehicle* GetTarget_AsVehicle();
MWObject* GetFiringTarget() const;
// const MWMover& GetBestTargetComponent() const;
void StartAttacking(MW4AI::Tactics::TacticID tactic, bool fOverrideCurrentMove = true, bool is_explicit = false);
void StopAttacking();
inline void KillTracking();
inline void UpdateFrameTiming();
void UpdateFriendlyFireTiming();
void UpdateSquad();
void UpdateMoving();
void UpdateThrottleOverride();
void UpdateAttacking();
void UpdateBeingTargeted();
void UpdateWaitingForHeatToReachZero();
void UpdateLookState();
void UpdateJumping();
void UpdateAutoTargeting();
void UpdateGoalPitchAndYaw();
void UpdateNoPathWarnings();
void UpdateCurrentVulnerableComponent();
void AttackExplicitFirePoint();
void OffsetTargetQuery(Entity__CollisionQuery& q) const;
void Execute_TrackToPoint(const Stuff::Point3D& point);
void MoveToPoint(const Stuff::Point3D& point, bool move_forward, bool dont_use_throttle = false, MWObject* ram_target = 0);
void StopMoving();
void SetSpeed(Stuff::Scalar speed);
Stuff::Scalar RecommendedCurrentSpeed();
void ModifyMood(Stuff::Scalar multiplier);
void ModifyChanceToHit(Stuff::Scalar& chance_to_hit, MWObject& target, const Stuff::LinearMatrix4D& my_matrix, Stuff::Scalar distance_from_target);
Stuff::Scalar ApproximateDistanceToTarget();
void TryToFire(MW4AI::FireStyles::FireStyleID style_id);
bool TryToFireAt(MW4AI::FireStyles::FireStyle& style, MWObject& who, bool should_hit);
bool MightBeAbleToFireAt(MW4AI::FireStyles::FireStyle& style, MWObject& who);
bool TryToHit(MWObject& who, MW4AI::FireStyles::FireStyle& style);
bool TryToHitAtPoints(MWObject& who, MW4AI::FireStyles::FireStyle& style, const std::list<AimPoint>& aim_points, bool can_hit_dead_components = false);
bool TryToMiss(MWObject& who, MW4AI::FireStyles::FireStyle& style);
inline Point3D GetFireSource();
bool ShotShouldHit(MWObject& who);
Stuff::Point3D GetNewAimPoint_ToMiss(MWObject& who, const Stuff::Point3D& self_pos);
bool Fire(MWObject& who, Adept::Entity* component, MW4AI::FireSource fire_source, const Stuff::LinearMatrix4D& matrix, const Stuff::Point3D& target_point, MW4AI::FireStyles::FireStyle& style, bool should_hit);
void FireAtAimPoint(MW4AI::FireStyles::FireStyle& style,
MechWarrior4::MWObject* who,
Adept::Entity* component,
MW4AI::FireSource fire_source,
const Stuff::LinearMatrix4D& source_matrix,
Adept::Entity* who_to_hit,
Vehicle* vehicle_shooting_at,
bool can_spend_ammo);
Adept::DamageObject* PickComponent(MWObject& who, const MW4AI::component_vector& components);
bool IsMovingQuickly(MWObject& who);
void InitializeSecondaryTargets(secondary_target_list& secondary_targets);
secondary_target_list::iterator SelectSecondaryTarget(secondary_target_list& secondary_targets);
inline bool CanOpportunityFire(MW4AI::FireStyles::FireStyle& style) const;
inline MWMover* GetEyeSitePointer();
inline void ResetTorso();
Stuff::Scalar CalcTorsoTwistDemand(const Point3D& point, MechWarrior4::Torso& torso, bool for_multi_torso);
Stuff::Scalar GetMaxFireCheatAngle();
bool IsLaserTurret();
bool SuicideIsOK() const;
void SetLookState(LookState state);
void SetLookState(const MW4AI::FireStyles::FireStyle& fire_style);
void SuggestPointWasNotAGoodDestination(const Stuff::Point3D& dest);
MW4AI::FireSource GetBestFireSource(MechWarrior4::MWObject& who);
MW4AI::FireSource GetBestFireSource(const Stuff::Point3D& target_point);
Stuff::LinearMatrix4D GetFireSourceMatrix(MW4AI::FireSource fire_source);
void GetAttackInterval(Stuff::Scalar& min, Stuff::Scalar& max);
bool ShouldSpendAmmoAgainst(MWObject& who, MW4AI::FireStyles::FireStyle& style);
void ThisIsAMethodToSetABreakpointInIfCurrentVehicle();
Stuff::Scalar GetNormalizedCurrentHeat() const;
bool LineMightHitFriendlyUnits(const Stuff::Line3D& line);
bool LeftmostOrRightmostWeaponHitsSomethingElse(const MW4AI::FireParamPackage& params);
void RefreshCanSeeResults();
Stuff::Scalar GetComponentScore(int armor_component, int internal_component, Stuff::Scalar max_score, bool is_left);
Stuff::Point3D GetLongTomPitchPoint();
bool CanFireNARC();
bool CanFireHeatGeneratingWeapons() const;
void SetFallDampingEnabled(bool enabled);
void CheapShot(MWObject& who, bool should_hit, bool should_spend_ammo);
Stuff::Scalar GetModifiedMaxTorsoTwistSpeed(MechWarrior4::Torso& torso);
void GetAimPoints(MWObject& who, std::list<AimPoint>& aim_points);
void MultiTurretFire(MW4AI::FireStyles::FireStyle& style);
MWObject* GetNearestEnemyToLine(Stuff::Line3D& line, const secondary_target_list& targets);
void OpportunityFire(MW4AI::FireStyles::FireStyle& style);
protected:
void NotifyNoPath();
virtual Stuff::Scalar GetMinSpeed() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Test Support
//
public:
void TestInstance() const;
};
inline void CombatAI::EnablePerWeaponRayCasting(bool enable)
{
m_PerWeaponRayCasting = enable;
}
inline void CombatAI::SetSquadOrders(Stuff::Auto_Ptr<MW4AI::SquadOrders>& orders)
{
m_SquadOrders = orders;
}
inline MW4AI::SquadOrders* CombatAI::GetSquadOrders()
{
return (m_SquadOrders.GetPointer());
}
inline bool CombatAI::TacticIsFinished() const
{
if (m_Tactic.GetPointer() == 0)
{
return (true);
}
return (m_Tactic->Finished());
}
inline MW4AI::Tactics::TacticID CombatAI::GetCurrentTactic() const
{
Verify(GetAttackState() == ATTACKING);
return (m_Tactic->GetID());
}
inline Stuff::Scalar CombatAI::GetAttackRadiusMultiplier() const
{
if (m_AttackRadiusMultiplier != 0)
{
return (m_AttackRadiusMultiplier);
}
return (GetMoodRadiusMultiplier());
}
inline MW4AI::SearchLightController& CombatAI::GetSearchLightController()
{
return (m_SearchLightController);
}
inline Stuff::Point3D CombatAI::GetMoveDest() const
{
return (m_LastMoveDest);
}
inline Stuff::Scalar CombatAI::GetLastTimeRammedTarget() const
{
return (m_LastTimeRammedTarget);
}
inline Stuff::Scalar CombatAI::GetLastTimeJumped() const
{
return (m_LastTimeJumped);
}
inline Stuff::Scalar CombatAI::GetTimeTargetedByEnemy() const
{
if (m_LastTargetedAlignment != GetSelf().GetAlignment())
{
return (m_TimeBeingTargeted);
}
return (0);
}
inline Stuff::Scalar CombatAI::GetTimeTargetedByFriendly() const
{
if (m_LastTargetedAlignment == GetSelf().GetAlignment())
{
return (m_TimeBeingTargeted);
}
return (0);
}
inline Stuff::Scalar CombatAI::GetSquadTargetingRadius() const
{
return (m_SquadTargetingRadius);
}
inline void CombatAI::SetSquadTargetingRadius(Stuff::Scalar radius)
{
m_SquadTargetingRadius = radius;
}
inline MWMover* CombatAI::GetEyeSitePointer()
{
return (GetSelf().eyeSitePointer.GetCurrent());
}
inline bool CombatAI::ShouldForceDestinationRecalc() const
{
return (m_ForceDestinationRecalc);
}
inline void CombatAI::ForceDestinationRecalc()
{
m_ForceDestinationRecalc = true;
}
inline MWObject& CombatAI::GetSelf()
{
Check_Pointer(getEntity());
Verify(getEntity()->IsDerivedFrom(MWObject::DefaultData));
return (*(Cast_Object(MWObject*,getEntity())));
}
inline const MWObject& CombatAI::GetSelf() const
{
Check_Pointer(getEntity());
Verify(getEntity()->IsDerivedFrom(MWObject::DefaultData));
return (*(Cast_Object(MWObject*,getEntity())));
}
inline MWObject& CombatAI::GetTarget()
{
Verify(Target() != 0);
Verify(Target()->IsDerivedFrom(MWObject::DefaultData));
return (*(Cast_Object(MWObject*,Target())));
}
inline Vehicle* CombatAI::GetSelf_AsVehicle()
{
MWObject& self = GetSelf();
if (self.IsDerivedFrom(Vehicle::DefaultData))
{
return (Cast_Object(Vehicle*,&self));
}
return (0);
}
inline const Vehicle* CombatAI::GetSelf_AsVehicle() const
{
const MWObject& self = GetSelf();
if (self.IsDerivedFrom(Vehicle::DefaultData))
{
return (Cast_Object(const Vehicle*,&self));
}
return (0);
}
inline Vehicle* CombatAI::GetTarget_AsVehicle()
{
MWObject& target = GetTarget();
if (target.IsDerivedFrom(Vehicle::DefaultData))
{
return (Cast_Object(Vehicle*,&target));
}
return (0);
}
inline void CombatAI::Execute_TurnToPoint(const Point3D& point)
{
MW4AI::AutoHeap local_heap(MW4AI::g_CombatAIHeap);
MW4AI::CommandEntry* turn = CreateTurnToCommand(point,false);
Check_Pointer(turn);
ExecuteCommand(turn);
}
inline void CombatAI::KillTracking()
{
MW4AI::AutoHeap local_heap(MW4AI::g_CombatAIHeap);
if (CanMove() == false)
{
return;
}
MW4AI::CommandEntry* kill_tracking = CreateKillTrackCommand();
Check_Pointer(kill_tracking);
ExecuteCommand(kill_tracking);
}
inline void CombatAI::ResetTorso()
{
MW4AI::AutoHeap local_heap(MW4AI::g_CombatAIHeap);
{for (std::vector<Torso*>::const_iterator i = GetSelf().GetTorsos().begin();
i != GetSelf().GetTorsos().end();
++i)
{
(*i)->yawDemand = 0;
(*i)->pitchDemand = 0;
}}
}
inline Point3D CombatAI::GetFireSource()
{
if (GetEyeSitePointer() != 0)
{
return ((Point3D)GetEyeSitePointer()->GetLocalToWorld());
}
return ((Point3D)GetSelf().GetLocalToWorld());
}
inline Stuff::Scalar CombatAI::GetAttackThrottle() const
{
return (m_AttackThrottle);
}
inline void CombatAI::SetAttackThrottle(Stuff::Scalar throttle)
{
Verify(throttle <= 100);
Verify(throttle >= 0);
m_AttackThrottle = throttle;
}
inline Stuff::Scalar CombatAI::GetBaseChanceToHit() const
{
return (GunnerySkill() * 0.01f);
}
inline void CombatAI::SetFiringDelay(Stuff::Scalar min, Stuff::Scalar max)
{
Verify(min >= 0);
Verify(max >= 0);
Verify(min <= max);
m_MinFiringDelay = min;
m_MaxFiringDelay = max;
}
inline bool CombatAI::ShouldHoldFireToAvoidFriendlyFire() const
{
if (m_FriendlyFireDelay == 0)
{
return (false);
}
return (gos_GetElapsedTime() <= m_LastFriendlyFireTime + m_FriendlyFireDelay);
}
inline MW4AI::TacticInterface& CombatAI::GetTacticInterface()
{
return (m_Interface);
}
inline Stuff::Scalar CombatAI::GetLastFiredTime() const
{
return (m_LastFireTime);
}
inline bool CombatAI::GetHoldingFire() const
{
return (m_HoldingFire);
}
inline void CombatAI::SetHoldingFire(bool hold_fire)
{
m_HoldingFire = hold_fire;
}
inline int CombatAI::GetNumArmsBlownOff() const
{
return (m_NumArmsBlownOff);
}
inline int CombatAI::GetNumLegsBlownOff() const
{
return (m_NumLegsBlownOff);
}
inline bool CombatAI::Attacking() const
{
return (GetAttackState() == ATTACKING);
}
inline CombatAI::AttackState CombatAI::GetAttackState() const
{
if (m_Tactic.GetPointer() == 0)
{
return (NOT_ATTACKING);
}
return (ATTACKING);
}
inline void CombatAI::UpdateFrameTiming()
{
m_ApproximateTimeBetweenFrames = gos_GetElapsedTime() - m_LastFrameTime;
m_LastFrameTime = gos_GetElapsedTime();
}
inline bool CombatAI::CanOpportunityFire(MW4AI::FireStyles::FireStyle& style) const
{
if (style.CanAlwaysFireAtSecondaryTargets() == true)
{
return (true);
}
Stuff::Scalar elite((Stuff::Scalar)EliteSkill());
if ((elite >= MW4AI::UserConstants::Instance()->Get(MW4AI::UserConstants::min_opportunity_fire)) &&
(elite <= MW4AI::UserConstants::Instance()->Get(MW4AI::UserConstants::max_opportunity_fire)))
{
return (true);
}
return (false);
}
inline bool CombatAI::RecentPathsFailed() const
{
return (m_MostRecentNoPathWarnings.size() > 1);
}
inline bool CombatAI::GetAutoTargeting() const
{
return (m_AutoTargetingEnabled);
}
inline void CombatAI::SetAutoTargeting(bool enabled)
{
m_AutoTargetingEnabled = enabled;
}
inline Stuff::Scalar CombatAI::GetCurrentVulnerableComponent() const
{
return (m_CurrentVulnerableComponent);
}
inline void CombatAI::SetIgnoreFog(bool ignore)
{
m_IgnoreFog = ignore;
}
inline bool CombatAI::GetIgnoreFog() const
{
return (m_IgnoreFog);
}
}
#endif // COMBATAI_HPP