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.
256 lines
7.5 KiB
C++
256 lines
7.5 KiB
C++
|
|
#pragma once
|
|
#ifndef AI_TACTICS_HPP
|
|
#define AI_TACTICS_HPP
|
|
|
|
#include <stuff\auto_container.hpp>
|
|
#pragma warning (push)
|
|
#include <stlport\string>
|
|
#include <stlport\vector>
|
|
#pragma warning (pop)
|
|
#include "AI_Behavior.hpp"
|
|
#include <Stuff\Scalar.hpp>
|
|
|
|
|
|
|
|
namespace Stuff { class Point3D; }
|
|
namespace MechWarrior4 { class Vehicle; }
|
|
|
|
namespace MW4AI
|
|
{
|
|
namespace Tactics
|
|
{
|
|
enum TacticID
|
|
{
|
|
// NOTE: The keywords and constants here must exactly match those in MWCONST.ABI
|
|
TACTIC_PICK_BEST = 2000, // update TACTIC_FIRST if you change this
|
|
TACTIC_STOP_AND_FIRE = 2001,
|
|
TACTIC_RAM = 2002,
|
|
TACTIC_JOUST = 2003,
|
|
TACTIC_RUSH = 2004,
|
|
TACTIC_HIT_AND_RUN = 2005,
|
|
TACTIC_FRONT = 2006,
|
|
TACTIC_REAR = 2007,
|
|
TACTIC_CIRCLE_OF_DEATH = 2008,
|
|
TACTIC_BACK_UP_AND_FIRE = 2009,
|
|
TACTIC_RETREAT = 2010,
|
|
TACTIC_CIRCLE_HOVER = 2011,
|
|
TACTIC_STRAFE = 2012,
|
|
TACTIC_STAND_GROUND = 2013,
|
|
TACTIC_JUMP_AND_SHOOT = 2014,
|
|
TACTIC_SNIPE = 2015,
|
|
TACTIC_SHOOT_ONLY = 2016,
|
|
TACTIC_DEFEND = 2017,
|
|
TACTIC_LOCAL_PATROL = 2018,
|
|
TACTIC_SURRENDER = 2019,
|
|
TACTIC_AMBUSH = 2020,
|
|
TACTIC_DEATH_FROM_ABOVE = 2021,
|
|
TACTIC_HELI_POPUP = 2022,
|
|
TACTIC_DIVE_BOMB = 2023,
|
|
TACTIC_FAST_CIRCLE = 2024,
|
|
TACTIC_STARE = 2025 // update TACTIC_LAST if you change this
|
|
};
|
|
|
|
class Tactic
|
|
{
|
|
public:
|
|
virtual void Update(TacticInterface& i);
|
|
|
|
virtual TacticID GetID() const = 0;
|
|
virtual std::string GetName() const = 0;
|
|
|
|
Tactic();
|
|
virtual ~Tactic();
|
|
|
|
virtual bool CanBeSelectedAutomatically(TacticInterface& iface) const;
|
|
virtual bool ShouldIgnoreLOS() const;
|
|
|
|
void SetExplicit(bool is_explicit);
|
|
bool GetExplicit() const;
|
|
|
|
bool ShouldAbandon(TacticInterface& i) const;
|
|
virtual bool ShouldAbandonImmediately() const = 0;
|
|
|
|
virtual Stuff::Scalar Evaluate(TacticInterface& iface) const;
|
|
|
|
void SetIgnoreExplicitTactic(TacticID tactic);
|
|
TacticID GetIgnoreExplicitTactic() const;
|
|
|
|
bool Finished() const;
|
|
|
|
void UpdateSatisfaction();
|
|
|
|
private:
|
|
Stuff::Scalar GetDuration() const;
|
|
bool IsIneffective() const;
|
|
|
|
Stuff::Scalar m_CreationTime;
|
|
Stuff::Scalar m_CreationMood;
|
|
mutable bool m_Explicit;
|
|
|
|
Stuff::Scalar m_Satisfaction;
|
|
Stuff::Time m_LastSatisfactionUpdate;
|
|
Stuff::Scalar m_AutoEndTime;
|
|
|
|
TacticID m_TacticToIgnore;
|
|
|
|
protected:
|
|
virtual bool IsHappy() const = 0;
|
|
};
|
|
|
|
enum
|
|
{
|
|
TACTIC_FIRST = TACTIC_PICK_BEST,
|
|
TACTIC_LAST = TACTIC_STARE
|
|
};
|
|
|
|
void VerifyTactic(TacticID id);
|
|
Stuff::Auto_Ptr<Tactic> CreateTactic(TacticInterface& i, TacticID id);
|
|
|
|
class Registrar
|
|
{
|
|
public:
|
|
static void IncrementRefCount(TacticInterface& i);
|
|
static void DecrementRefCount();
|
|
static Registrar& GetInstance();
|
|
|
|
Registrar(TacticInterface& i);
|
|
~Registrar();
|
|
|
|
TacticID SelectTactic(TacticInterface& i, const std::vector<TacticID>& most_recent_tactics) const;
|
|
Tactic& GetTactic(TacticID id) const;
|
|
|
|
private:
|
|
int m_RefCount;
|
|
static Registrar* instance;
|
|
typedef Stuff::Auto_Container<Tactic,std::vector<Tactic*> > tactic_container;
|
|
tactic_container m_Tactics;
|
|
};
|
|
|
|
#define BEGINDEF_TACTIC(classname,id,string_name,behavior_type) \
|
|
class classname: \
|
|
public Tactic \
|
|
{ \
|
|
protected: \
|
|
TacticID GetID() const { return (id); } \
|
|
std::string GetName() const { return (string_name); } \
|
|
bool ShouldAbandonImmediately() const { return (m_Implementation.ShouldStopImmediately()); } \
|
|
void Update(TacticInterface& i) \
|
|
{ \
|
|
Tactic::Update(i); \
|
|
m_Implementation.Execute(i); \
|
|
} \
|
|
bool IsHappy() const { return (m_Implementation.IsHappy()); } \
|
|
private: \
|
|
behavior_type m_Implementation;
|
|
|
|
#define ENDDEF_TACTIC };
|
|
|
|
BEGINDEF_TACTIC(StopAndFire,TACTIC_STOP_AND_FIRE,"Stop and Fire",MW4AI::Behaviors::StopAndFire)
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(Ram,TACTIC_RAM,"Ram",MW4AI::Behaviors::Ram)
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(Joust,TACTIC_JOUST,"Joust",MW4AI::Behaviors::Joust);
|
|
public:
|
|
bool CanBeSelectedAutomatically(TacticInterface& iface) const;
|
|
Stuff::Scalar Evaluate(TacticInterface& iface) const;
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(Rush,TACTIC_RUSH,"Rush",MW4AI::Behaviors::Rush)
|
|
public:
|
|
bool CanBeSelectedAutomatically(TacticInterface& iface) const;
|
|
Stuff::Scalar Evaluate(TacticInterface& iface) const;
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(HitAndRun,TACTIC_HIT_AND_RUN,"Hit and Run",MW4AI::Behaviors::HitAndRun)
|
|
public:
|
|
bool CanBeSelectedAutomatically(TacticInterface& iface) const;
|
|
Stuff::Scalar Evaluate(TacticInterface& iface) const;
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(Front,TACTIC_FRONT,"Front",MW4AI::Behaviors::Front)
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(Rear,TACTIC_REAR,"Rear",MW4AI::Behaviors::Rear)
|
|
public:
|
|
bool CanBeSelectedAutomatically(TacticInterface& iface) const;
|
|
Stuff::Scalar Evaluate(TacticInterface& iface) const;
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(Circle,TACTIC_CIRCLE_OF_DEATH,"Circle",MW4AI::Behaviors::CircleOfDeath)
|
|
public:
|
|
bool CanBeSelectedAutomatically(TacticInterface& iface) const;
|
|
Stuff::Scalar Evaluate(TacticInterface& iface) const;
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(Retreat,TACTIC_RETREAT,"Retreat",MW4AI::Behaviors::Retreat)
|
|
public:
|
|
bool CanBeSelectedAutomatically(TacticInterface& iface) const;
|
|
Stuff::Scalar Evaluate(TacticInterface& iface) const;
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(BackUpAndFire,TACTIC_BACK_UP_AND_FIRE,"Back Up and Fire",MW4AI::Behaviors::BackUpAndFire)
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(CircleHover,TACTIC_CIRCLE_HOVER,"Circle Hover",MW4AI::Behaviors::CircleHover)
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(Strafe,TACTIC_STRAFE,"Strafe",MW4AI::Behaviors::Strafe)
|
|
virtual bool ShouldIgnoreLOS() const
|
|
{
|
|
return (true);
|
|
}
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(StandGround,TACTIC_STAND_GROUND,"Stand Ground",MW4AI::Behaviors::StandGround)
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(JumpAndShoot,TACTIC_JUMP_AND_SHOOT,"Jump and Shoot",MW4AI::Behaviors::JumpAndShoot)
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(Snipe,TACTIC_SNIPE,"Snipe",MW4AI::Behaviors::Snipe)
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(ShootOnly,TACTIC_SHOOT_ONLY,"ShootOnly",MW4AI::Behaviors::ShootOnly)
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(Defend,TACTIC_DEFEND,"Defend",MW4AI::Behaviors::Defend)
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(LocalPatrol,TACTIC_LOCAL_PATROL,"Local Patrol",MW4AI::Behaviors::LocalPatrol)
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(Surrender,TACTIC_SURRENDER,"Surrender",MW4AI::Behaviors::Surrender)
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(Ambush,TACTIC_AMBUSH,"Ambush",MW4AI::Behaviors::Ambush)
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(DeathFromAbove,TACTIC_DEATH_FROM_ABOVE,"Death From Above",MW4AI::Behaviors::DeathFromAbove)
|
|
public:
|
|
bool CanBeSelectedAutomatically(TacticInterface& iface) const;
|
|
Stuff::Scalar Evaluate(TacticInterface& iface) const;
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(HeliPopup,TACTIC_HELI_POPUP,"Heli Popup",MW4AI::Behaviors::HeliPopup)
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(DiveBomb,TACTIC_DIVE_BOMB,"Dive Bomb",MW4AI::Behaviors::DiveBomb)
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(FastCircle,TACTIC_FAST_CIRCLE,"Fast Circle",MW4AI::Behaviors::FastCircle)
|
|
ENDDEF_TACTIC
|
|
|
|
BEGINDEF_TACTIC(Stare,TACTIC_STARE,"Stare",MW4AI::Behaviors::Stare)
|
|
ENDDEF_TACTIC
|
|
|
|
#undef BEGINDEF_TACTIC
|
|
#undef ENDDEF_TACTIC
|
|
};
|
|
};
|
|
|
|
|
|
#endif AI_TACTICS_HPP
|