#pragma once
/** Classes to handle the Tutorials.
*/
using std::vector;
using std::string;
class PlayingGameState;
class Tutorial;
#include "sector.h"
class TutorialInfo {
public:
string id;
string text;
TutorialInfo(const string &id, const string &text) : id(id), text(text) {
}
};
class TutorialManager {
public:
static vector<TutorialInfo> getTutorialInfo();
static Tutorial *setupTutorial(const string &id);
};
class GUIHandler {
public:
virtual void setGUI(PlayingGameState *playing_gamestate) const {
}
virtual ~GUIHandler() {
// need a virtual destructor even though it doesn't do anything, to ensure that subclass destructors are called (see warning on Linux GCC)
}
static void resetGUI(PlayingGameState *playing_gamestate);
};
class GUIHandlerBlockAll : public GUIHandler {
vector<string> exceptions;
public:
virtual void setGUI(PlayingGameState *playing_gamestate) const;
void addException(const string &exception) {
exceptions.push_back(exception);
}
};
class TutorialCard {
string id;
string text;
string next_text;
bool has_arrow;
int arrow_x, arrow_y;
bool show_arrow_on_page;
int show_arrow_page;
bool show_arrow_on_sector;
int show_arrow_sector_x;
int show_arrow_sector_y;
bool auto_proceed;
bool player_allow_build_tower;
GUIHandler *gui_handler;
public:
TutorialCard(const string &id, const string &text) : id(id), text(text), next_text("Next"), has_arrow(false), arrow_x(-1), arrow_y(-1), show_arrow_on_page(false), show_arrow_page(-1), show_arrow_on_sector(false), show_arrow_sector_x(-1), show_arrow_sector_y(-1), auto_proceed(false), player_allow_build_tower(true), gui_handler(NULL) {
}
virtual ~TutorialCard() {
if( gui_handler != NULL ) {
delete gui_handler;
}
}
string getId() const {
return id;
}
string getText() const {
return text;
}
void setNextText(const string &next_text) {
this->next_text = next_text;
}
string getNextText() const {
return next_text;
}
void setArrow(int arrow_x, int arrow_y) {
this->has_arrow = true;
this->arrow_x = arrow_x;
this->arrow_y = arrow_y;
}
void setArrowShowPage(int show_arrow_page) {
this->show_arrow_on_page = true;
this->show_arrow_page = show_arrow_page;
}
void setArrowShowSector(int show_arrow_sector_x, int show_arrow_sector_y) {
this->show_arrow_on_sector = true;
this->show_arrow_sector_x = show_arrow_sector_x;
this->show_arrow_sector_y = show_arrow_sector_y;
}
bool hasArrow(PlayingGameState *playing_gamestate) const;
int getArrowX() const {
return arrow_x;
}
int getArrowY() const {
return arrow_y;
}
void setAutoProceed(bool auto_proceed) {
this->auto_proceed = auto_proceed;
}
bool autoProceed() const {
return auto_proceed;
}
virtual bool canProceed(PlayingGameState *playing_gamestate) const {
return true;
}
void setPlayerAllowBuildTower(bool player_allow_build_tower) {
this->player_allow_build_tower = player_allow_build_tower;
}
bool playerAllowBuildTower() const {
return player_allow_build_tower;
}
virtual void setGUI(PlayingGameState *playing_gamestate) const;
void setGUIHandler(GUIHandler *gui_handler) {
this->gui_handler = gui_handler;
}
};
class TutorialCardWaitForPanelPage : public TutorialCard {
int wait_page;
public:
TutorialCardWaitForPanelPage(const string &id, const string &text, int wait_page) : TutorialCard(id, text), wait_page(wait_page) {
this->setAutoProceed(true);
}
virtual bool canProceed(PlayingGameState *playing_gamestate) const;
};
class TutorialCardWaitForDesign : public TutorialCard {
public:
enum WaitType {
WAITTYPE_CURRENT_DESIGN = 0,
WAITTYPE_HAS_DESIGNED = 1,
WAITTYPE_CURRENT_MANUFACTURE = 2,
WAITTYPE_HAS_MANUFACTURED = 3
};
private:
const Sector *sector;
WaitType wait_type;
bool require_type;
Invention::Type invention_type;
bool require_epoch;
int invention_epoch;
public:
TutorialCardWaitForDesign(const string &id, const string &text, const Sector *sector, WaitType wait_type, bool require_type, Invention::Type invention_type, bool require_epoch, int invention_epoch) : TutorialCard(id, text), sector(sector), wait_type(wait_type), require_type(require_type), invention_type(invention_type), require_epoch(require_epoch), invention_epoch(invention_epoch) {
this->setAutoProceed(true);
}
virtual bool canProceed(PlayingGameState *playing_gamestate) const;
};
class TutorialCardWaitForBuilding : public TutorialCard {
const Sector *sector;
Type building_type;
public:
TutorialCardWaitForBuilding(const string &id, const string &text, const Sector *sector, Type building_type) : TutorialCard(id, text), sector(sector), building_type(building_type) {
this->setAutoProceed(true);
}
virtual bool canProceed(PlayingGameState *playing_gamestate) const;
};
class TutorialCardWaitForDeployedArmy : public TutorialCard {
Sector *deploy_sector;
bool require_bombard;
bool inverse; // if true, wait until an army is deployed anywhere other than deploy_sector (or anywhere, if deploy_sector is NULL)
bool require_empty; // if true, check the square(s) is empty instead
bool require_unoccupied; // if true, require that the square is not occupied by a player's tower
public:
TutorialCardWaitForDeployedArmy(const string &id, const string &text, Sector *deploy_sector, bool require_bombard) : TutorialCard(id, text), deploy_sector(deploy_sector), require_bombard(require_bombard), inverse(false), require_empty(false), require_unoccupied(false) {
this->setAutoProceed(true);
}
void setInverse(bool inverse) {
this->inverse = inverse;
}
void setRequireEmpty(bool require_empty) {
this->require_empty = require_empty;
}
void setRequireUnoccupied(bool require_unoccupied) {
this->require_unoccupied = require_unoccupied;
}
virtual bool canProceed(PlayingGameState *playing_gamestate) const;
};
class TutorialCardWaitForNewTower : public TutorialCard {
Sector *tower_sector;
bool inverse; // if true, wait until a tower is built anywhere other than tower_sector (or anywhere, if tower_sector is NULL)
public:
TutorialCardWaitForNewTower(const string &id, const string &text, Sector *tower_sector) : TutorialCard(id, text), tower_sector(tower_sector), inverse(false) {
this->setAutoProceed(true);
}
void setInverse(bool inverse) {
this->inverse = inverse;
}
virtual bool canProceed(PlayingGameState *playing_gamestate) const;
};
class Tutorial {
protected:
string id;
int start_epoch;
int island;
int start_map_x, start_map_y;
int n_men;
bool auto_end;
size_t card_index;
vector<TutorialCard *> cards;
bool ai_allow_growth;
bool ai_allow_design;
bool ai_allow_ask_alliance;
bool ai_allow_deploy;
bool allow_retreat_loss;
public:
Tutorial(const string &id) : id(id), start_epoch(0), island(0), start_map_x(0), start_map_y(0), n_men(0), auto_end(false), card_index(0), ai_allow_growth(true), ai_allow_design(true), ai_allow_ask_alliance(true), ai_allow_deploy(true), allow_retreat_loss(true) {
}
virtual ~Tutorial();
string getId() const {
return id;
}
int getStartEpoch() const {
return start_epoch;
}
int getIsland() const {
return island;
}
int getStartMapX() const {
return start_map_x;
}
int getStartMapY() const {
return start_map_y;
}
int getNMen() const {
return n_men;
}
bool aiAllowGrowth() const {
return ai_allow_growth;
}
bool aiAllowDesign() const {
return ai_allow_design;
}
bool aiAllowAskAlliance() const {
return ai_allow_ask_alliance;
}
bool aiAllowDeploy() const {
return ai_allow_deploy;
}
bool allowRetreatLoss() const {
return allow_retreat_loss;
}
const TutorialCard *getCard() const {
if( card_index >= cards.size() )
return NULL;
return cards.at(card_index);
}
void proceed() {
card_index++;
}
bool jumpTo(const string &id);
void jumpToEnd() {
card_index = cards.size();
}
bool autoEnd() const {
return auto_end;
}
virtual void initCards()=0;
};
class Tutorial1 : public Tutorial {
public:
Tutorial1(const string &id);
virtual void initCards();
};
class Tutorial2 : public Tutorial {
public:
Tutorial2(const string &id);
virtual void initCards();
};
class Tutorial3 : public Tutorial {
public:
Tutorial3(const string &id);
virtual void initCards();
};