pioneer/src/ShipAICmd.h

244 lines
6.4 KiB
C++

// Copyright © 2008-2021 Pioneer Developers. See AUTHORS.txt for details
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
#ifndef _SHIPAICMD_H
#define _SHIPAICMD_H
#include "GameSaveError.h"
#include "JsonFwd.h"
#include "DynamicBody.h"
#include "FrameId.h"
#include "FixedGuns.h"
#include "ship/Propulsion.h"
class Ship;
class Space;
class SpaceStation;
class AICommand {
public:
// This enum is solely to make the serialization work
enum CmdName { // <enum scope='AICommand::CmdName' name=ShipAICmdName public>
CMD_NONE,
CMD_DOCK,
CMD_FLYTO,
CMD_FLYAROUND,
CMD_KILL,
CMD_KAMIKAZE,
CMD_HOLDPOSITION,
CMD_FORMATION
};
AICommand(DynamicBody *dBody, CmdName name) :
m_dBody(dBody),
m_cmdName(name)
{
m_dBody->AIMessage(DynamicBody::AIERROR_NONE);
}
virtual ~AICommand() {}
virtual bool TimeStepUpdate() = 0;
bool ProcessChild(); // returns false if child is active
virtual void GetStatusText(char *str)
{
if (m_child)
m_child->GetStatusText(str);
else
strcpy(str, "AI state unknown");
}
// Serialisation functions
static AICommand *LoadFromJson(const Json &jsonObj);
AICommand(const Json &jsonObj, CmdName name);
virtual void SaveToJson(Json &jsonObj);
virtual void PostLoadFixup(Space *space);
// Signal functions
virtual void OnDeleted(const Body *body)
{
if (m_child) m_child->OnDeleted(body);
}
CmdName GetType() const { return m_cmdName; }
protected:
DynamicBody *m_dBody;
RefCountedPtr<Propulsion> m_prop;
RefCountedPtr<FixedGuns> m_fguns;
std::unique_ptr<AICommand> m_child;
bool m_is_flyto;
CmdName m_cmdName;
int m_dBodyIndex; // deserialisation
};
class AICmdDock : public AICommand {
public:
virtual bool TimeStepUpdate();
AICmdDock(DynamicBody *dBody, SpaceStation *target);
virtual void GetStatusText(char *str);
virtual void SaveToJson(Json &jsonObj);
AICmdDock(const Json &jsonObj);
virtual void PostLoadFixup(Space *space);
virtual void OnDeleted(const Body *body);
private:
enum EDockingStates {
eDockGetDataStart = 0, // 0: get data for docking start pos
eDockFlyToStart = 1, // 1: Fly to docking start pos
eDockGetDataEnd = 2, // 2: get data for docking end pos
eDockFlyToEnd = 3, // 3: Fly to docking end pos
eDockingComplete = 4,
eInvalidDockingStage = 5
};
SpaceStation *m_target;
vector3d m_dockpos; // offset in target's frame
vector3d m_dockdir;
vector3d m_dockupdir;
EDockingStates m_state; // see TimeStepUpdate()
int m_targetIndex; // used during deserialisation
void IncrementState()
{
switch (m_state) {
case eDockGetDataStart: m_state = eDockFlyToStart; break;
case eDockFlyToStart: m_state = eDockGetDataEnd; break;
case eDockGetDataEnd: m_state = eDockFlyToEnd; break;
case eDockFlyToEnd: m_state = eDockingComplete; break;
case eDockingComplete: m_state = eInvalidDockingStage; break;
case eInvalidDockingStage: break;
}
}
};
class AICmdFlyTo : public AICommand {
public:
virtual bool TimeStepUpdate();
AICmdFlyTo(DynamicBody *dBody, FrameId targframeId, const vector3d &posoff, double endvel, bool tangent);
AICmdFlyTo(DynamicBody *dBody, Body *target);
virtual void GetStatusText(char *str);
virtual void SaveToJson(Json &jsonObj);
AICmdFlyTo(const Json &jsonObj);
virtual void PostLoadFixup(Space *space);
virtual void OnDeleted(const Body *body);
private:
Body *m_target; // target for vicinity. Either this or targframe is 0
double m_dist; // vicinity distance
FrameId m_targframeId; // target frame for waypoint
vector3d m_posoff; // offset in target frame
double m_endvel; // target speed in direction of motion at end of path, positive only
bool m_tangent; // true if path is to a tangent of the target frame's body
int m_state;
bool m_lockhead;
int m_targetIndex; // used during deserialisation
vector3d m_reldir; // target direction relative to ship at last frame change
FrameId m_frameId; // last frame of ship
};
class AICmdFlyAround : public AICommand {
public:
virtual bool TimeStepUpdate();
AICmdFlyAround(DynamicBody *dBody, Body *obstructor, double relalt, int mode = 2);
AICmdFlyAround(DynamicBody *dBody, Body *obstructor, double alt, double vel, int mode = 1);
virtual void GetStatusText(char *str);
virtual void SaveToJson(Json &jsonObj);
AICmdFlyAround(const Json &jsonObj);
virtual void PostLoadFixup(Space *space);
virtual void OnDeleted(const Body *body)
{
AICommand::OnDeleted(body);
// check against obstructor?
}
void SetTargPos(const vector3d &targpos)
{
m_targpos = targpos;
m_targmode = 0;
}
protected:
void Setup(Body *obstructor, double alt, double vel, int mode);
double MaxVel(double targdist, double targalt);
private:
Body *m_obstructor; // body to fly around
int m_obstructorIndex; // deserialisation
double m_alt, m_vel;
int m_targmode; // 0 targpos termination, 1 infinite, 2+ orbital termination
vector3d m_targpos; // target position in ship space
};
class AICmdKill : public AICommand {
public:
virtual bool TimeStepUpdate();
AICmdKill(DynamicBody *dBody, Ship *target);
AICmdKill(const Json &jsonObj);
~AICmdKill();
// don't actually need to save all this crap
virtual void SaveToJson(Json &jsonObj);
void PostLoadFixup(Space *space);
virtual void OnDeleted(const Body *body);
private:
Ship *m_target;
double m_leadTime, m_evadeTime, m_closeTime;
vector3d m_leadOffset, m_leadDrift, m_lastVel;
int m_targetIndex; // used during deserialisation
};
class AICmdKamikaze : public AICommand {
public:
virtual bool TimeStepUpdate();
AICmdKamikaze(DynamicBody *dBody, Body *target);
virtual void SaveToJson(Json &jsonObj);
AICmdKamikaze(const Json &jsonObj);
virtual void PostLoadFixup(Space *space);
virtual void OnDeleted(const Body *body);
private:
Body *m_target;
int m_targetIndex; // used during deserialisation
};
class AICmdHoldPosition : public AICommand {
public:
virtual bool TimeStepUpdate();
AICmdHoldPosition(DynamicBody *dBody);
AICmdHoldPosition(const Json &jsonObj);
};
class AICmdFormation : public AICommand {
public:
virtual bool TimeStepUpdate();
AICmdFormation(DynamicBody *dBody, DynamicBody *target, const vector3d &posoff);
void GetStatusText(char *str);
virtual void SaveToJson(Json &jsonObj);
AICmdFormation(const Json &jsonObj);
virtual void PostLoadFixup(Space *space);
virtual void OnDeleted(const Body *body);
private:
DynamicBody *m_target; // target frame for waypoint
vector3d m_posoff; // offset in target frame
int m_targetIndex; // used during deserialisation
};
#endif /* _SHIPAICMD_H */