diff --git a/ADG5.cpp b/ADG5.cpp index 3149c62..c1a55f2 100644 --- a/ADG5.cpp +++ b/ADG5.cpp @@ -24,12 +24,14 @@ int main(int argc, char **argv) auto context = tcod::Context(params); engine = new Engine(80, 50, &context, &console); - engine->init(); + engine->load(); while (engine->update()) { engine->render(); } + engine->save(); + delete engine; return 0; diff --git a/Actor.cpp b/Actor.cpp index fe63ce0..19d55fd 100644 --- a/Actor.cpp +++ b/Actor.cpp @@ -37,4 +37,56 @@ float Actor::getDistance(int cx, int cy) const { int dx = x - cx; int dy = y - cy; return sqrtf(dx * dx + dy * dy); +} + +void Actor::save(TCODZip& zip) { + zip.putInt(x); + zip.putInt(y); + zip.putString(std::string(ch).c_str()); + zip.putInt(col.r); + zip.putInt(col.g); + zip.putInt(col.b); + zip.putString(name.c_str()); + zip.putInt(blocks); + zip.putInt(attacker != NULL); + zip.putInt(destructible != NULL); + zip.putInt(ai != NULL); + zip.putInt(pickable != NULL); + zip.putInt(container != NULL); + if (attacker) attacker->save(zip); + if (destructible) destructible->save(zip); + if (ai) ai->save(zip); + if (pickable) pickable->save(zip); + if (container) container->save(zip); +} + +void Actor::load(TCODZip& zip) { + x = zip.getInt(); + y = zip.getInt(); + ch = std::string(zip.getString()); + col = TCOD_ColorRGB(zip.getInt(), zip.getInt(), zip.getInt()); + name = zip.getString(); + blocks = zip.getInt(); + bool hasAttacker = zip.getInt(); + bool hasDestructible = zip.getInt(); + bool hasAi = zip.getInt(); + bool hasPickable = zip.getInt(); + bool hasContainer = zip.getInt(); + if (hasAttacker) { + attacker = new Attacker(0.0f); + attacker->load(zip); + } + if (hasDestructible) { + destructible = Destructible::create(zip); + } + if (hasAi) { + ai = Ai::create(zip); + } + if (hasPickable) { + pickable = Pickable::create(zip); + } + if (hasContainer) { + container = new Container(0); + container->load(zip); + } } \ No newline at end of file diff --git a/Actor.h b/Actor.h index e1e919a..715a79f 100644 --- a/Actor.h +++ b/Actor.h @@ -1,6 +1,7 @@ #pragma once #include "libtcod.hpp" +#include "Persistance.h" class Attacker; class Destructible; @@ -8,11 +9,11 @@ class Ai; class Pickable; class Container; -class Actor { +class Actor : public Persistent { public: int x, y; // position on map - std::string_view ch; // ascii code + std::string ch; // ascii code TCOD_ColorRGB col; // color std::string name; bool blocks; @@ -26,4 +27,7 @@ public: ~Actor(); void render(TCOD_Console& cons) const; void update(); + void load(TCODZip& zip); + void save(TCODZip& zip); + }; \ No newline at end of file diff --git a/Ai.cpp b/Ai.cpp index c26e6ae..a20e55b 100644 --- a/Ai.cpp +++ b/Ai.cpp @@ -258,3 +258,41 @@ void ConfusedMonsterAi::update(Actor* owner) { delete this; } } + +Ai* Ai::create(TCODZip& zip) { + AiType type = (AiType)zip.getInt(); + Ai* ai = NULL; + switch (type) { + case PLAYER: ai = new PlayerAi(); break; + case MONSTER: ai = new MonsterAi(); break; + case CONFUSED_MONSTER: ai = new ConfusedMonsterAi(0, NULL); break; + } + ai->load(zip); + return ai; +} +void MonsterAi::load(TCODZip& zip) { + moveCount = zip.getInt(); +} + +void MonsterAi::save(TCODZip& zip) { + zip.putInt(MONSTER); + zip.putInt(moveCount); +} + +void ConfusedMonsterAi::load(TCODZip& zip) { + nbTurns = zip.getInt(); + oldAi = Ai::create(zip); +} + +void ConfusedMonsterAi::save(TCODZip& zip) { + zip.putInt(CONFUSED_MONSTER); + zip.putInt(nbTurns); + oldAi->save(zip); +} + +void PlayerAi::load(TCODZip& zip) { +} + +void PlayerAi::save(TCODZip& zip) { + zip.putInt(PLAYER); +} \ No newline at end of file diff --git a/Ai.h b/Ai.h index 2528c07..396fef9 100644 --- a/Ai.h +++ b/Ai.h @@ -1,17 +1,25 @@ #pragma once +#include "libtcod.hpp" +#include "Persistance.h" class Actor; -class Ai { +class Ai : public Persistent { public: virtual void update(Actor* owner) = 0; virtual ~Ai() {}; + static Ai* create(TCODZip& zip); +protected: + enum AiType { + MONSTER, CONFUSED_MONSTER, PLAYER + }; }; class PlayerAi : public Ai { public: void update(Actor* owner); - + void load(TCODZip& zip); + void save(TCODZip& zip); protected: bool moveOrAttack(Actor* owner, int targetx, int targety); void handleActionKey(Actor* owner, int sdlkey); @@ -21,7 +29,8 @@ protected: class MonsterAi : public Ai { public: void update(Actor* owner); - + void load(TCODZip& zip); + void save(TCODZip& zip); protected: int moveCount; void moveOrAttack(Actor* owner, int targetx, int targety); @@ -31,6 +40,8 @@ class ConfusedMonsterAi : public Ai { public: ConfusedMonsterAi(int nbTurns, Ai* oldAi); void update(Actor* owner); + void load(TCODZip& zip); + void save(TCODZip& zip); protected: int nbTurns; Ai* oldAi; diff --git a/Attacker.cpp b/Attacker.cpp index e45f96c..0973597 100644 --- a/Attacker.cpp +++ b/Attacker.cpp @@ -22,3 +22,11 @@ void Attacker::attack(Actor* owner, Actor* target) { engine->gui->message(TCOD_ColorRGB(150, 150, 150), "%s attacks %s in vain.\n", owner->name.c_str(), target->name.c_str()); } } + +void Attacker::load(TCODZip& zip) { + power = zip.getFloat(); +} + +void Attacker::save(TCODZip& zip) { + zip.putFloat(power); +} \ No newline at end of file diff --git a/Attacker.h b/Attacker.h index 142f936..9988890 100644 --- a/Attacker.h +++ b/Attacker.h @@ -1,11 +1,16 @@ #pragma once +#include "libtcod.hpp" +#include "Persistance.h" + class Actor; -class Attacker { +class Attacker : public Persistent { public: float power; // hit points given Attacker(float power); void attack(Actor* owner, Actor* target); + void load(TCODZip& zip); + void save(TCODZip& zip); }; \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b35f72..729ac33 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ project ("ADG5") find_package(libtcod CONFIG REQUIRED) # Add source to this project's executable. -add_executable (ADG5 "ADG5.cpp" "ADG5.h" "Actor.cpp" "Actor.h" "Map.h" "Map.cpp" "Engine.h" "Engine.cpp" "Destructible.h" "Destructible.cpp" "Attacker.h" "Attacker.cpp" "Ai.h" "Ai.cpp" "Gui.h" "Gui.cpp" "Container.h" "Container.cpp" "Pickable.h" "Pickable.cpp" "Healer.h" "Healer.cpp" "Lightningbolt.h" "Lightningbolt.cpp" "Fireball.h" "Fireball.cpp" "Confuser.h" "Confuser.cpp") +add_executable (ADG5 "ADG5.cpp" "ADG5.h" "Actor.cpp" "Actor.h" "Map.h" "Map.cpp" "Engine.h" "Engine.cpp" "Destructible.h" "Destructible.cpp" "Attacker.h" "Attacker.cpp" "Ai.h" "Ai.cpp" "Gui.h" "Gui.cpp" "Container.h" "Container.cpp" "Pickable.h" "Pickable.cpp" "Healer.h" "Healer.cpp" "Lightningbolt.h" "Lightningbolt.cpp" "Fireball.h" "Fireball.cpp" "Confuser.h" "Confuser.cpp" "Persistance.h") target_link_libraries(ADG5 PRIVATE diff --git a/Confuser.cpp b/Confuser.cpp index ea292c2..e6b13c7 100644 --- a/Confuser.cpp +++ b/Confuser.cpp @@ -25,4 +25,15 @@ bool Confuser::use(Actor* owner, Actor* wearer) { engine->gui->message(TCOD_ColorRGB(100, 255, 100), "The eyes of the %s look vacant,\nas he starts to stumble around!", actor->name.c_str()); return Pickable::use(owner, wearer); +} + +void Confuser::load(TCODZip& zip) { + nbTurns = zip.getInt(); + range = zip.getFloat(); +} + +void Confuser::save(TCODZip& zip) { + zip.putInt(CONFUSER); + zip.putInt(nbTurns); + zip.putFloat(range); } \ No newline at end of file diff --git a/Confuser.h b/Confuser.h index 2a54dc6..9b89e08 100644 --- a/Confuser.h +++ b/Confuser.h @@ -10,4 +10,6 @@ public: float range; Confuser(int nbTurns, float range); bool use(Actor* owner, Actor* wearer); + void load(TCODZip& zip); + void save(TCODZip& zip); }; \ No newline at end of file diff --git a/Container.cpp b/Container.cpp index 1ab47e9..c972403 100644 --- a/Container.cpp +++ b/Container.cpp @@ -1,4 +1,5 @@ #include "Container.h" +#include "Actor.h" Container::Container(int size) : size(size) { } @@ -18,4 +19,23 @@ bool Container::add(Actor* actor) { void Container::remove(Actor* actor) { inventory.remove(actor); +} + +void Container::load(TCODZip& zip) { + size = zip.getInt(); + int nbActors = zip.getInt(); + while (nbActors > 0) { + Actor* actor = new Actor(0, 0, "?", "", TCOD_ColorRGB(255, 255, 255)); + actor->load(zip); + inventory.push(actor); + nbActors--; + } +} + +void Container::save(TCODZip& zip) { + zip.putInt(size); + zip.putInt(inventory.size()); + for (Actor** it = inventory.begin(); it != inventory.end(); it++) { + (*it)->save(zip); + } } \ No newline at end of file diff --git a/Container.h b/Container.h index de4f00a..f7e33d6 100644 --- a/Container.h +++ b/Container.h @@ -1,9 +1,9 @@ #pragma once #include "libtcod.hpp" - +#include "Persistance.h" class Actor; -class Container { +class Container : public Persistent { public: int size; // maximum number of actors. 0=unlimited TCODList inventory; @@ -12,4 +12,6 @@ public: ~Container(); bool add(Actor* actor); void remove(Actor* actor); + void load(TCODZip& zip); + void save(TCODZip& zip); }; \ No newline at end of file diff --git a/Destructible.cpp b/Destructible.cpp index 6475026..79ad5e5 100644 --- a/Destructible.cpp +++ b/Destructible.cpp @@ -47,6 +47,16 @@ PlayerDestructible::PlayerDestructible(float maxHp, float defense, std::string c Destructible(maxHp, defense, corpseName) { } +void PlayerDestructible::save(TCODZip& zip) { + zip.putInt(PLAYER); + Destructible::save(zip); +} + +void MonsterDestructible::save(TCODZip& zip) { + zip.putInt(MONSTER); + Destructible::save(zip); +} + void MonsterDestructible::die(Actor* owner) { // transform it into a nasty corpse! it doesn't block, can't be // attacked and doesn't move @@ -58,4 +68,29 @@ void PlayerDestructible::die(Actor* owner) { engine->gui->message(TCOD_ColorRGB(150, 0, 0), "You died!\n"); Destructible::die(owner); engine->gameStatus = Engine::DEFEAT; +} + +void Destructible::load(TCODZip& zip) { + maxHp = zip.getFloat(); + hp = zip.getFloat(); + defense = zip.getFloat(); + corpseName = zip.getString(); +} + +void Destructible::save(TCODZip& zip) { + zip.putFloat(maxHp); + zip.putFloat(hp); + zip.putFloat(defense); + zip.putString(corpseName.c_str()); +} + +Destructible* Destructible::create(TCODZip& zip) { + DestructibleType type = (DestructibleType)zip.getInt(); + Destructible* destructible = NULL; + switch (type) { + case MONSTER: destructible = new MonsterDestructible(0, 0, ""); break; + case PLAYER: destructible = new PlayerDestructible(0, 0, ""); break; + } + destructible->load(zip); + return destructible; } \ No newline at end of file diff --git a/Destructible.h b/Destructible.h index 63f4d7d..3b7bfb0 100644 --- a/Destructible.h +++ b/Destructible.h @@ -1,9 +1,12 @@ #pragma once #include +#include "libtcod.hpp" +#include "Persistance.h" + class Actor; -class Destructible { +class Destructible : public Persistent { public: float maxHp; // maximum health points float hp; // current health points @@ -17,16 +20,25 @@ public: virtual void die(Actor* owner); float heal(float amount); + void load(TCODZip& zip); + void save(TCODZip& zip); + static Destructible* create(TCODZip& zip); +protected: + enum DestructibleType { + MONSTER, PLAYER + }; }; class MonsterDestructible : public Destructible { public: MonsterDestructible(float maxHp, float defense, std::string corpseName); + void save(TCODZip& zip); void die(Actor* owner); }; class PlayerDestructible : public Destructible { public: PlayerDestructible(float maxHp, float defense, std::string corpseName); + void save(TCODZip& zip); void die(Actor* owner); }; \ No newline at end of file diff --git a/Engine.cpp b/Engine.cpp index d8c65f0..aa89efe 100644 --- a/Engine.cpp +++ b/Engine.cpp @@ -35,6 +35,7 @@ void Engine::init() { player->container = new Container(26); actors.push(player); map = new Map(80, 45); + map->init(true); gui->message(TCOD_ColorRGB(150,0,0), "Welcome stranger!\nPrepare to perish in the Tombs of Andrew's Dunegon."); } @@ -169,4 +170,59 @@ Actor* Engine::getActor(int x, int y) const { } } return nullptr; +} + +void Engine::save() { + if (player->destructible->isDead()) { + TCODSystem::deleteFile("game.sav"); + } + else { + TCODZip zip; + // save the map first + zip.putInt(map->width); + zip.putInt(map->height); + map->save(zip); + // then the player + player->save(zip); + // then all the other actors + zip.putInt(actors.size() - 1); + for (Actor** it = actors.begin(); it != actors.end(); it++) { + if (*it != player) { + (*it)->save(zip); + } + } + // finally the message log + gui->save(zip); + zip.saveToFile("game.sav"); + } +} + +void Engine::load() { + if (TCODSystem::fileExists("game.sav")) { + TCODZip zip; + zip.loadFromFile("game.sav"); + // load the map + int width = zip.getInt(); + int height = zip.getInt(); + map = new Map(width, height); + map->load(zip); + // then the player + player = new Actor(0, 0, "?", "", TCOD_ColorRGB(255, 255, 255)); + player->load(zip); + actors.push(player); + // then all other actors + int nbActors = zip.getInt(); + while (nbActors > 0) { + Actor* actor = new Actor(0, 0, "?", "", TCOD_ColorRGB(255, 255, 255)); + actor->load(zip); + actors.push(actor); + nbActors--; + } + // finally the message log + gui = new Gui(context, console); + gui->load(zip); + } + else { + engine->init(); + } } \ No newline at end of file diff --git a/Engine.h b/Engine.h index 4e5f509..20f50b3 100644 --- a/Engine.h +++ b/Engine.h @@ -35,6 +35,8 @@ public: Actor* getClosestMonster(int x, int y, float range) const; bool pickATile(int* x, int* y, float maxRange = 0.0f); Actor* getActor(int x, int y) const; + void load(); + void save(); private: bool computeFov; }; diff --git a/Fireball.cpp b/Fireball.cpp index 94e665d..dbe0753 100644 --- a/Fireball.cpp +++ b/Fireball.cpp @@ -27,4 +27,10 @@ bool Fireball::use(Actor* owner, Actor* wearer) { } } return Pickable::use(owner, wearer); +} + +void Fireball::save(TCODZip& zip) { + zip.putInt(FIREBALL); + zip.putFloat(range); + zip.putFloat(damage); } \ No newline at end of file diff --git a/Fireball.h b/Fireball.h index 4ee8b83..4eead34 100644 --- a/Fireball.h +++ b/Fireball.h @@ -7,4 +7,5 @@ class Fireball : public LightningBolt { public: Fireball(float range, float damage); bool use(Actor* owner, Actor* wearer); + void save(TCODZip& zip); }; \ No newline at end of file diff --git a/Gui.cpp b/Gui.cpp index 7a950ea..65e7023 100644 --- a/Gui.cpp +++ b/Gui.cpp @@ -115,4 +115,25 @@ void Gui::renderMouseLook() { } } tcod::print(con, { 1, 0 }, buf, TCOD_ColorRGB(200, 200, 200), std::nullopt); +} + +void Gui::save(TCODZip& zip) { + zip.putInt(log.size()); + for (Message** it = log.begin(); it != log.end(); it++) { + zip.putString((*it)->text.c_str()); + zip.putInt((*it)->col.r); + zip.putInt((*it)->col.g); + zip.putInt((*it)->col.b); + + } +} + +void Gui::load(TCODZip& zip) { + int nbMessages = zip.getInt(); + while (nbMessages > 0) { + const char* text = zip.getString(); + TCOD_ColorRGB col(zip.getInt(), zip.getInt(), zip.getInt()); + message(col, text); + nbMessages--; + } } \ No newline at end of file diff --git a/Gui.h b/Gui.h index 609b3c5..2bf5d6d 100644 --- a/Gui.h +++ b/Gui.h @@ -1,13 +1,15 @@ #pragma once #include "libtcod.hpp" - -class Gui { +#include "Persistance.h" +class Gui : public Persistent { public: Gui(tcod::Context *ctx, tcod::Console *root); ~Gui(); void render(); void message(const TCOD_ColorRGB& col, const char* text, ...); + void load(TCODZip& zip); + void save(TCODZip& zip); protected: tcod::Console con; diff --git a/Healer.cpp b/Healer.cpp index cbf5663..47716a5 100644 --- a/Healer.cpp +++ b/Healer.cpp @@ -13,4 +13,13 @@ bool Healer::use(Actor* owner, Actor* wearer) { } } return false; +} + +void Healer::load(TCODZip& zip) { + amount = zip.getFloat(); +} + +void Healer::save(TCODZip& zip) { + zip.putInt(HEALER); + zip.putFloat(amount); } \ No newline at end of file diff --git a/Healer.h b/Healer.h index a2f001e..0939632 100644 --- a/Healer.h +++ b/Healer.h @@ -9,4 +9,6 @@ public: Healer(float amount); bool use(Actor* owner, Actor* wearer); ~Healer() {}; + void load(TCODZip& zip); + void save(TCODZip& zip); }; diff --git a/Lightningbolt.cpp b/Lightningbolt.cpp index 99299e1..c1f6c0e 100644 --- a/Lightningbolt.cpp +++ b/Lightningbolt.cpp @@ -16,9 +16,20 @@ bool LightningBolt::use(Actor* owner, Actor* wearer) { } // hit closest monster for hit points engine->gui->message(TCOD_ColorRGB(100, 255, 100), - "A lighting bolt strikes the %s with a loud crack of thunder!\n" + "A lighting bolt strikes the %s with a crack of thunder!\n" "The damage is %g hit points.", closestMonster->name.c_str(), damage); closestMonster->destructible->takeDamage(closestMonster, damage); return Pickable::use(owner, wearer); +} + +void LightningBolt::load(TCODZip& zip) { + range = zip.getFloat(); + damage = zip.getFloat(); +} + +void LightningBolt::save(TCODZip& zip) { + zip.putInt(LIGHTNING_BOLT); + zip.putFloat(range); + zip.putFloat(damage); } \ No newline at end of file diff --git a/Lightningbolt.h b/Lightningbolt.h index d4b617e..54e8f20 100644 --- a/Lightningbolt.h +++ b/Lightningbolt.h @@ -9,4 +9,6 @@ public: float range, damage; LightningBolt(float range, float damage); bool use(Actor* owner, Actor* wearer); + void load(TCODZip& zip); + void save(TCODZip& zip); }; \ No newline at end of file diff --git a/Map.cpp b/Map.cpp index 17c8069..0049642 100644 --- a/Map.cpp +++ b/Map.cpp @@ -24,15 +24,16 @@ private: public: BspListener(Map& map) : map(map), roomNum(0) {} bool visitNode(TCODBsp* node, void* userData) { + if (node->isLeaf()) { int x, y, w, h; + bool withActors = (bool)userData; // dig a room - TCODRandom* rng = TCODRandom::getInstance(); - w = rng->getInt(ROOM_MIN_SIZE, node->w - 2); - h = rng->getInt(ROOM_MIN_SIZE, node->h - 2); - x = rng->getInt(node->x + 1, node->x + node->w - w - 1); - y = rng->getInt(node->y + 1, node->y + node->h - h - 1); - map.createRoom(roomNum == 0, x, y, x + w - 1, y + h - 1); + w = map.rng->getInt(ROOM_MIN_SIZE, node->w - 2); + h = map.rng->getInt(ROOM_MIN_SIZE, node->h - 2); + x = map.rng->getInt(node->x + 1, node->x + node->w - w - 1); + y = map.rng->getInt(node->y + 1, node->y + node->h - h - 1); + map.createRoom(roomNum == 0, x, y, x + w - 1, y + h - 1, withActors); if (roomNum != 0) { // dig a corridor from last room map.dig(lastx, lasty, x + w / 2, lasty); @@ -47,14 +48,17 @@ public: }; Map::Map(int width, int height) : width(width), height(height) { + seed = TCODRandom::getInstance()->getInt(0, 0x7FFFFFFF); +} +void Map::init(bool withActors) { + rng = new TCODRandom(seed, TCOD_RNG_CMWC); tiles = new Tile[width * height]; map = new TCODMap(width, height); TCODBsp bsp(0, 0, width, height); - bsp.splitRecursive(NULL, 8, ROOM_MAX_SIZE, ROOM_MAX_SIZE, 1.5f, 1.5f); + bsp.splitRecursive(rng, 8, ROOM_MAX_SIZE, ROOM_MAX_SIZE, 1.5f, 1.5f); BspListener listener(*this); - bsp.traverseInvertedLevelOrder(&listener, NULL); + bsp.traverseInvertedLevelOrder(&listener, (void*)withActors); } - Map::~Map() { delete[] tiles; delete map; @@ -140,8 +144,11 @@ void Map::dig(int x1, int y1, int x2, int y2) { } } -void Map::createRoom(bool first, int x1, int y1, int x2, int y2) { +void Map::createRoom(bool first, int x1, int y1, int x2, int y2, bool withActors) { dig(x1, y1, x2, y2); + if (!withActors) { + return; + } if (first) { // put the player in the first room engine->player->x = (x1 + x2) / 2; @@ -228,4 +235,19 @@ void Map::addItem(int x, int y) { scrollOfConfusion->pickable = new Confuser(10, 8); engine->actors.push(scrollOfConfusion); } +} + +void Map::save(TCODZip& zip) { + zip.putInt(seed); + for (int i = 0; i < width * height; i++) { + zip.putInt(tiles[i].explored); + } +} + +void Map::load(TCODZip& zip) { + seed = zip.getInt(); + init(false); + for (int i = 0; i < width * height; i++) { + tiles[i].explored = zip.getInt(); + } } \ No newline at end of file diff --git a/Map.h b/Map.h index 600201d..6d297fe 100644 --- a/Map.h +++ b/Map.h @@ -1,16 +1,19 @@ #pragma once +#include "libtcod.hpp" +#include "Persistance.h" struct Tile { bool explored; // has the player already seen this tile ? Tile() : explored(false) {} }; -class Map { +class Map : public Persistent { public: int width, height; Map(int width, int height); ~Map(); + void init(bool withActors); bool canWalk(int x, int y) const; bool isWall(int x, int y) const; bool isInFov(int x, int y) const; @@ -18,12 +21,17 @@ public: void computeFov(); void render(TCOD_Console& cons) const; void addItem(int x, int y); + long seed; + TCODRandom* rng; + void load(TCODZip& zip); + void save(TCODZip& zip); + protected: Tile* tiles; friend class BspListener; TCODMap* map; void dig(int x1, int y1, int x2, int y2); - void createRoom(bool first, int x1, int y1, int x2, int y2); + void createRoom(bool first, int x1, int y1, int x2, int y2, bool withActors); void addMonster(int x, int y); void setWall(int x, int y); }; \ No newline at end of file diff --git a/Persistance.h b/Persistance.h new file mode 100644 index 0000000..7da2a9b --- /dev/null +++ b/Persistance.h @@ -0,0 +1,7 @@ +#pragma once + +class Persistent { +public: + virtual void load(TCODZip& zip) = 0; + virtual void save(TCODZip& zip) = 0; +}; \ No newline at end of file diff --git a/Pickable.cpp b/Pickable.cpp index dd96170..c258dc7 100644 --- a/Pickable.cpp +++ b/Pickable.cpp @@ -3,6 +3,11 @@ #include "Engine.h" #include "Container.h" #include "Gui.h" +#include "Healer.h" +#include "LightningBolt.h" +#include "Confuser.h" +#include "Fireball.h" + bool Pickable::pick(Actor* owner, Actor* wearer) { if (wearer->container && wearer->container->add(owner)) { @@ -30,4 +35,17 @@ void Pickable::drop(Actor* owner, Actor* wearer) { engine->gui->message(TCOD_ColorRGB(200,200,200), "%s drops a %s.", wearer->name.c_str(), owner->name.c_str()); } +} + +Pickable* Pickable::create(TCODZip& zip) { + PickableType type = (PickableType)zip.getInt(); + Pickable* pickable = NULL; + switch (type) { + case HEALER: pickable = new Healer(0); break; + case LIGHTNING_BOLT: pickable = new LightningBolt(0, 0); break; + case CONFUSER: pickable = new Confuser(0, 0); break; + case FIREBALL: pickable = new Fireball(0, 0); break; + } + pickable->load(zip); + return pickable; } \ No newline at end of file diff --git a/Pickable.h b/Pickable.h index 855cf83..1ddc919 100644 --- a/Pickable.h +++ b/Pickable.h @@ -1,11 +1,18 @@ #pragma once +#include "libtcod.hpp" +#include "Persistance.h" class Actor; -class Pickable { +class Pickable : public Persistent { public: bool pick(Actor* owner, Actor* wearer); virtual bool use(Actor* owner, Actor* wearer); void drop(Actor* owner, Actor* wearer); virtual ~Pickable() {}; + static Pickable* create(TCODZip& zip); +protected: + enum PickableType { + HEALER, LIGHTNING_BOLT, CONFUSER, FIREBALL + }; };