I'm trying to find a way to allow both input and AI to call actions of an actor in a component based structure for a 2d turn based game. The actions make use of the components. To keep the system flexible I don't want to statically set what actions the actor has in the actor class.
Right now I have action classes who have ids and I'm using maps to hold the actions and allow the input and AI to execute actions by calling a function in the actor class. Now I've run into all sorts of issues like it not working well with using different parameter types or amounts and other things. So is there a better way to do what I try to achieve?
This is my actor class that holds a map with actions that take two ints:
class Actor
{
friend Scene; /* allows the scene to move the acotr */
public:
Actor();
~Actor();
int getCellX() { return m_CellX; }
int getCellY() { return m_CellY; }
void addComponent(Component* component);
void addAction(PositionAction*);
bool executeAction(string, int, int);
private:
int m_CellX = 0;
int m_CellY = 0;
map<string, Component*> m_Components;
map<string, PositionAction*> m_PositionActions;
map<string, TargetableActorAction*> m_TargetableActorActions;
};
This shows the hierarchy of the action class:
class Action
{
public:
Action();
~Action();
virtual string getID() = 0; /* used to identify the action in the map */
};
class PositionAction : public Action
{
public:
PositionAction();
~PositionAction();
virtual bool execute(int, int) = 0;
};
class MoveAction : public PositionAction
{
public:
MoveAction(MoveComponent&);
~MoveAction();
bool execute(int, int);
string getID() { return "move"; }
private:
MoveComponent& m_MoveComponent;
};
And this is what the move action does:
MoveAction::MoveAction(MoveComponent& moveComponent) : m_MoveComponent(moveComponent)
{
}
MoveAction::~MoveAction()
{
}
bool MoveAction::execute(int dX, int dY)
{
/* will check whether some conditions hold */
/* move the actor, returns false if failed */
bool sucess = m_MoveComponent.move(dX, dY);
return sucess;
}
This creates the player actor with a move component and the move action.
Actor* player = new Actor();
MoveComponent* moveComponent = new MoveComponent(scene);
player->addComponent(moveComponent);
player->addAction(new MoveAction(*moveComponent));
return player;
And you can execute an action like this:
actor.executeAction("move", 1, 0);