1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#ifndef _COMMAND_AI_H
#define _COMMAND_AI_H
#include <functional>
#include <vector>
#include "System/Object.h"
#include "CommandDescription.h"
#include "CommandQueue.h"
#include "System/float3.h"
#include "System/UnorderedSet.hpp"
class CUnit;
class CFeature;
class CWeapon;
struct Command;
class CCommandAI : public CObject
{
CR_DECLARE_DERIVED(CCommandAI)
public:
CCommandAI(CUnit* owner);
CCommandAI();
virtual ~CCommandAI();
void DependentDied(CObject* o) override;
static void InitCommandDescriptionCache();
static void KillCommandDescriptionCache();
inline void SetOrderTarget(CUnit* o);
virtual void AddDeathDependence(CObject* o, DependenceType dep) override;
virtual void DeleteDeathDependence(CObject* o, DependenceType dep) override;
void AddCommandDependency(const Command& c);
void ClearCommandDependencies();
// these both feed into GiveCommandReal()
void GiveCommand(const Command& c, bool fromSynced = true ); // sim
void GiveCommand(const Command& c, int playerNum, bool fromSynced , bool fromLua); // net,Lua
void ClearTargetLock(const Command& fc);
void WeaponFired(CWeapon* weapon, const bool searchForNewTarget);
virtual bool CanWeaponAutoTarget(const CWeapon* weapon) const { return true; }
virtual int GetDefaultCmd(const CUnit* pointed, const CFeature* feature);
virtual void SlowUpdate();
virtual void GiveCommandReal(const Command& c, bool fromSynced = true);
virtual void FinishCommand();
virtual void BuggerOff(const float3& pos, float radius) {}
virtual void StopMove() {}
void StopAttackingTargetIf(const std::function<bool(const CUnit*)>& pred);
void StopAttackingAllyTeam(int ally);
/**
* @brief Determines if c will cancel a queued command
* @return true if c will cancel a queued command
*/
bool WillCancelQueued(const Command& c) const;
bool HasCommand(int cmdID) const;
bool HasMoreMoveCommands(bool skipFirstCmd = true) const;
int CancelCommands(const Command& c, CCommandQueue& queue, bool& first);
/**
* @brief Finds the queued command that would be canceled by the Command c
* @return An iterator pointing at the command, or commandQue.end(),
* if no such queued command exists
*/
CCommandQueue::const_iterator GetCancelQueued(const Command& c, const CCommandQueue& queue) const;
/**
* @brief Returns commands that overlap c, but will not be canceled by c
* @return a vector containing commands that overlap c
*/
std::vector<Command> GetOverlapQueued(const Command& c) const;
std::vector<Command> GetOverlapQueued(const Command& c, const CCommandQueue& queue) const;
const std::vector<const SCommandDescription*>& GetPossibleCommands() const { return possibleCommands; }
/**
* @brief Causes this CommandAI to execute the attack order c
*/
virtual void ExecuteAttack(Command& c);
/**
* @brief executes the stop command c
*/
virtual void ExecuteStop(Command& c);
void UpdateCommandDescription(unsigned int cmdDescIdx, const Command& cmd);
void UpdateCommandDescription(unsigned int cmdDescIdx, SCommandDescription&& modCmdDesc);
void InsertCommandDescription(unsigned int cmdDescIdx, SCommandDescription&& cmdDesc);
bool RemoveCommandDescription(unsigned int cmdDescIdx);
void UpdateNonQueueingCommands();
void SetCommandDescParam0(const Command& c);
bool ExecuteStateCommand(const Command& c);
void ExecuteInsert(const Command& c, bool fromSynced = true);
void ExecuteRemove(const Command& c);
void AddStockpileWeapon(CWeapon* weapon);
void StockpileChanged(CWeapon* weapon);
void UpdateStockpileIcon();
bool CanChangeFireState() const;
virtual bool AllowedCommand(const Command& c, bool fromSynced);
CWeapon* stockpileWeapon;
std::vector<const SCommandDescription*> possibleCommands;
spring::unordered_set<int> nonQueingCommands;
CCommandQueue commandQue;
int lastUserCommand;
int selfDCountdown;
int lastFinishCommand;
CUnit* owner;
CUnit* orderTarget;
bool targetDied;
bool inCommand;
bool repeatOrders;
int lastSelectedCommandPage;
protected:
// return true by default so non-AirCAI's trigger FinishCommand
virtual bool SelectNewAreaAttackTargetOrPos(const Command& ac) { return true; }
bool IsAttackCapable() const;
bool SkipParalyzeTarget(const CUnit* target) const;
void GiveAllowedCommand(const Command& c, bool fromSynced = true);
void GiveWaitCommand(const Command& c);
/**
* @brief Returns the command that keeps the unit close to the path
* @return a Fight Command with 6 arguments, the first three being where to
* return to (the current position of the unit), and the second being
* the location of the original command.
*/
void PushOrUpdateReturnFight(const float3& cmdPos1, const float3& cmdPos2);
int UpdateTargetLostTimer(int unitID);
void DrawDefaultCommand(const Command& c) const;
private:
// FIXME make synced?
spring::unsynced_set<CObject*> commandDeathDependences;
/**
* continuously set to some non-zero value while target is in radar
* decremented by 1 every SlowUpdate (!), command is canceled when
* timer reaches 0
*/
int targetLostTimer;
};
inline void CCommandAI::SetOrderTarget(CUnit* o) {
if (orderTarget != NULL) {
// NOTE As we do not include Unit.h,
// the compiler does not know that CUnit derives from CObject,
// and thus we can not use static_cast<CObject*>(...) here.
DeleteDeathDependence(reinterpret_cast<CObject*>(orderTarget), DEPENDENCE_ORDERTARGET);
}
orderTarget = o;
if (orderTarget != NULL) {
AddDeathDependence(reinterpret_cast<CObject*>(orderTarget), DEPENDENCE_ORDERTARGET);
}
}
#endif // _COMMAND_AI_H
|