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.
1051 lines
27 KiB
C++
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
|