ICT290 / src / scene / AIController / Goals / Goal.h
Goal.h
Raw
#pragma once
// struct Telegram;
//#include "misc/cgdi.h"
//#include "misc/TypeToString.h"

#include "../Messaging/Telegram.h"

struct Telegram;

template <class entity_type>
struct Goal {
   public:
    enum { active, inactive, completed, failed };

   protected:
    // an enumerated type specifying the type of goal
    int m_Type;

    // a pointer to the entity that owns this goal
    entity_type* m_Owner;

    // an enumerated value indicating the goal's status (active, inactive,
    // completed, failed)
    int m_Status;

    /* the following methods were created to factor out some of the commonality
       in the implementations of the Process method() */

    // if m_Status = inactive this method sets it to active and calls Activate()
    void activateIfInactive();

    // if m_Status is failed this method sets it to inactive so that the goal
    // will be reactivated (and therefore re-planned) on the next update-step.
    void reactivateIfFailed();

   public:
    // note how goals start off in the inactive state
    Goal(entity_type* pE, int type)
        : m_Type(type),
          m_Owner(pE),
          m_Status(inactive) {}

    virtual ~Goal() {}

    // logic to run when the goal is activated.
    virtual void Activate() = 0;

    // logic to run each update-step
    virtual int Process() = 0;

    // logic to run when the goal is satisfied. (typically used to switch
    // off any active steering behaviors)
    virtual void Terminate() = 0;

    // goals can handle messages. Many don't though, so this defines a default
    // behavior
    virtual bool HandleMessage(const Telegram&) { return false; }

    virtual void markOwnerWithGoal() = 0;

    bool isComplete() const { return m_Status == completed; }
    bool isActive() const { return m_Status == active; }
    bool isInactive() const { return m_Status == inactive; }
    bool hasFailed() const { return m_Status == failed; }
    int getType() const { return m_Type; }

    /*
    //this is used to draw the name of the goal at the specific position
    //used for debugging
    virtual void RenderAtPos(Vector2D& pos, TypeToString* tts)const;

    //used to render any goal specific information
    virtual void Render(){}
     */
};

// if m_Status is failed this method sets it to inactive so that the goal
// will be reactivated (replanned) on the next update-step.
template <class entity_type>
void Goal<entity_type>::reactivateIfFailed() {
    if (hasFailed()) {
        m_Status = inactive;
    }
}

template <class entity_type>
void Goal<entity_type>::activateIfInactive() {
    if (isInactive()) {
        Activate();
    }
}