diff options
-rw-r--r-- | Changelog | 8 | ||||
-rw-r--r-- | include/entities.hpp | 11 | ||||
-rw-r--r-- | include/mob.hpp | 7 | ||||
-rw-r--r-- | include/save_util.hpp | 36 | ||||
-rw-r--r-- | include/world.hpp | 3 | ||||
-rw-r--r-- | main.cpp | 52 | ||||
-rw-r--r-- | src/entities.cpp | 45 | ||||
-rw-r--r-- | src/mob.cpp | 80 | ||||
-rw-r--r-- | src/world.cpp | 117 | ||||
-rw-r--r-- | xml/playerSpawnHill1.xml | 34 |
10 files changed, 223 insertions, 170 deletions
@@ -1035,3 +1035,11 @@ - found bugs in quest handling... - making lights and stars n stuff goood - story??? art??? music??? + +6/8/2016: +========= + + - entity stats are saved within the XML files, .dat's are gone + - game is overall better + - following lights, good lights + - good diff --git a/include/entities.hpp b/include/entities.hpp index e406397..b04705c 100644 --- a/include/entities.hpp +++ b/include/entities.hpp @@ -16,6 +16,7 @@ #include <quest.hpp> #include <inventory.hpp> #include <texture.hpp> +#include <save_util.hpp> // local library includes #include <tinyxml2.h> @@ -241,6 +242,7 @@ public: // constructs the entity with an XML thing-thang virtual void createFromXML(XMLElement *e, World *w=nullptr) =0; + virtual void saveToXML(void) =0; // a common constructor, clears variables Entity(void); @@ -259,6 +261,7 @@ public: void save(void); void sspawn(float x,float y); void createFromXML(XMLElement *e, World *w); + void saveToXML(void); }; class Structures : public Entity { @@ -273,6 +276,7 @@ public: unsigned int spawn(BUILD_SUB, float, float); void createFromXML(XMLElement *e, World *w); + void saveToXML(void); }; @@ -293,9 +297,10 @@ public: void addAIFunc(bool preload); - virtual void interact(); - virtual void wander(int); + void interact(); + void wander(int); void createFromXML(XMLElement *e, World *w); + void saveToXML(void); }; class Merchant : public NPC { @@ -317,6 +322,7 @@ public: ~Merchant(); void wander(int); + void saveToXML(void); }; class Object : public Entity{ @@ -338,6 +344,7 @@ public: return (name == o.name) && (loc == o.loc); } void createFromXML(XMLElement *e, World *w); + void saveToXML(void); }; /** diff --git a/include/mob.hpp b/include/mob.hpp index 450cf69..0dd50ac 100644 --- a/include/mob.hpp +++ b/include/mob.hpp @@ -8,6 +8,7 @@ #include <entities.hpp> #include <gametime.hpp> #include <ui.hpp> +#include <save_util.hpp> // local library headers #include <tinyxml2.h> @@ -60,6 +61,7 @@ public: void onHit(unsigned int); bool bindTex(void); void createFromXML(XMLElement *e, World *w) final; + void saveToXML(void) final; }; class Door : public Mob { @@ -70,6 +72,7 @@ public: void onHit(unsigned int); bool bindTex(void); void createFromXML(XMLElement *e, World *w) final; + void saveToXML(void) final; }; class Cat : public Mob { @@ -80,6 +83,7 @@ public: void onHit(unsigned int); bool bindTex(void); void createFromXML(XMLElement *e, World *w) final; + void saveToXML(void) final; }; class Rabbit : public Mob { @@ -90,6 +94,7 @@ public: void onHit(unsigned int); bool bindTex(void); void createFromXML(XMLElement *e, World *w) final; + void saveToXML(void) final; }; class Bird : public Mob { @@ -102,6 +107,7 @@ public: void onHit(unsigned int); bool bindTex(void); void createFromXML(XMLElement *e, World *w) final; + void saveToXML(void) final; }; class Trigger : public Mob { @@ -115,6 +121,7 @@ public: void onHit(unsigned int); bool bindTex(void); void createFromXML(XMLElement *e, World *w) final; + void saveToXML(void) final; }; #endif // MOB_H_ diff --git a/include/save_util.hpp b/include/save_util.hpp new file mode 100644 index 0000000..3d5cf54 --- /dev/null +++ b/include/save_util.hpp @@ -0,0 +1,36 @@ +#ifndef SAVE_UTIL_H_ +#define SAVE_UTIL_H_ + +/* + * Save macros. + */ + +#define E_SAVE_COORDS { xmle->SetAttribute("x", loc.x); xmle->SetAttribute("y", loc.y); } + +#define E_SAVE_HEALTH xmle->SetAttribute("health", health); + +/* + * Load macos. + */ + +#define E_LOAD_COORDS(yy) { float n; \ + if (xmle->QueryFloatAttribute("x", &n) == XML_NO_ERROR) \ + spawn(n, yy); \ + else \ + spawn(xmle->FloatAttribute("spawnx"), 100); \ + \ + if (xmle->QueryFloatAttribute("y", &n) == XML_NO_ERROR) \ + loc.y = n; } + +#define E_LOAD_HEALTH { float n; \ + \ + if (xmle->QueryFloatAttribute("maxHealth", &n) != XML_NO_ERROR) \ + maxHealth = 1; \ + \ + if (xmle->QueryFloatAttribute("health", &n) == XML_NO_ERROR) \ + health = n; \ + else \ + health = maxHealth; } + + +#endif // SAVE_UTIL_H_ diff --git a/include/world.hpp b/include/world.hpp index 26811ae..c5730f8 100644 --- a/include/world.hpp +++ b/include/world.hpp @@ -401,9 +401,6 @@ public: // saves the world's data to an XML file void save(void); - // attempts to load world data from an XML file - void load(void); - // plays/pauses the world's music, according to if a new world is being entered void bgmPlay(World *prev) const; @@ -112,8 +112,10 @@ void mainLoop(void); ** MAIN ************************************************************************ ********************************************************************************/ -int main(int argc, char *argv[]){ +int main(int argc, char *argv[]) +{ static SDL_GLContext mainGLContext = NULL; + static bool worldReset = false; // handle command line arguments if (argc > 1) { @@ -123,7 +125,7 @@ int main(int argc, char *argv[]){ for (const auto &s : args) { if (s == "--reset" || s == "-r") - system("rm -f xml/*.dat"); + worldReset = true; } } @@ -243,18 +245,48 @@ int main(int argc, char *argv[]){ if (xmlFolder.empty()) xmlFolder = "xml/"; - if (currentWorld == nullptr) { - // read in all XML file names in the folder - std::vector<std::string> xmlFiles; - if (getdir(std::string("./" + xmlFolder).c_str(), xmlFiles)) - UserError("Error reading XML files!!!"); + // read in all XML file names in the folder + std::vector<std::string> xmlFiles; + if (getdir(std::string("./" + xmlFolder).c_str(), xmlFiles)) + UserError("Error reading XML files!!!"); + + // alphabetically sort files + strVectorSortAlpha(&xmlFiles); + + if (worldReset) { + for (const auto &xf : xmlFiles) { + if (xf[0] != '.') { + XMLDocument xmld; + xmld.LoadFile(xf.c_str()); + + auto xmle = xmld.FirstChildElement("World"); + + if (xmle == nullptr) + xmle = xmld.FirstChildElement("IndoorWorld"); + + if (xmle == nullptr) + continue; - // alphabetically sort files - strVectorSortAlpha(&xmlFiles); + xmle = xmle->FirstChildElement(); + std::cout << xmle->Name() << '\n'; + while (xmle) { + xmle->DeleteAttribute("x"); + xmle->DeleteAttribute("y"); + xmle->DeleteAttribute("health"); + xmle->DeleteAttribute("alive"); + xmle->DeleteAttribute("dindex"); + xmle = xmle->NextSiblingElement(); + } + xmld.SaveFile(xf.c_str(), false); + } + } + } + if (currentWorld == nullptr) { + // load the first valid XML file for the world for (const auto &xf : xmlFiles) { - if (xf[0] != '.' && strcmp(&xf[xf.size() - 3], "dat")){ + if (xf[0] != '.') { // read it in std::cout << "File to load: " << xf << '\n'; currentWorld = loadWorldFromXML(xf); diff --git a/src/entities.cpp b/src/entities.cpp index f59b462..01255d5 100644 --- a/src/entities.cpp +++ b/src/entities.cpp @@ -195,6 +195,9 @@ void Player::createFromXML(XMLElement *e, World *w=nullptr) (void)w; } +void Player::saveToXML(void) +{} + NPC::NPC() : Entity() { width = HLINES(10); @@ -229,14 +232,12 @@ void NPC::createFromXML(XMLElement *e, World *w=nullptr) { std::string npcname; bool dialog; - float spawnx, Xhealth; unsigned int flooor; + xmle = e; + // spawn at coordinates if desired - if (e->QueryFloatAttribute("x", &spawnx) == XML_NO_ERROR) - spawn(spawnx, 100); - else - spawn(0, 100); + E_LOAD_COORDS(100); // name override if (!(npcname = e->StrAttribute("name")).empty()) @@ -254,11 +255,18 @@ void NPC::createFromXML(XMLElement *e, World *w=nullptr) Indoorp(w)->moveToFloor(this, flooor); // custom health value - if (e->QueryFloatAttribute("health", &Xhealth) == XML_NO_ERROR) { - health = maxHealth = Xhealth; - } + E_LOAD_HEALTH; - xmle = e; + // dialog index + if (e->QueryUnsignedAttribute("dindex", &flooor) == XML_NO_ERROR) + dialogIndex = flooor; +} + +void NPC::saveToXML(void) +{ + E_SAVE_HEALTH; + E_SAVE_COORDS; + xmle->SetAttribute("dindex", dialogIndex); } Merchant::Merchant() : NPC() @@ -294,6 +302,8 @@ Merchant::~Merchant() { } +void Merchant::saveToXML(void){} + Structures::Structures() : Entity() { canMove = false; @@ -308,13 +318,25 @@ void Structures::createFromXML(XMLElement *e, World *w) { float spawnx; + if (e->QueryBoolAttribute("alive", &alive) == XML_NO_ERROR && !alive) { + die(); + return; + } + inWorld = w; inside = e->StrAttribute("inside"); textureLoc = e->StrAttribute("texture"); spawn(static_cast<BUILD_SUB>(e->UnsignedAttribute("type")), - e->QueryFloatAttribute("x", &spawnx) == XML_NO_ERROR ? spawnx : (randGet() % w->getTheWidth() / 2.0f), + e->QueryFloatAttribute("spawnx", &spawnx) == XML_NO_ERROR ? spawnx : (randGet() % w->getTheWidth() / 2.0f), 100); + + xmle = e; +} + +void Structures::saveToXML(void) +{ + xmle->SetAttribute("alive", alive); } Object::Object() @@ -346,6 +368,9 @@ void Object::createFromXML(XMLElement *e, World *w=nullptr) (void)w; } +void Object::saveToXML(void) +{} + void Object::reloadTexture(void) { tex = TextureIterator({getItemTexturePath(iname)}); diff --git a/src/mob.cpp b/src/mob.cpp index 526d7b1..4cafa09 100644 --- a/src/mob.cpp +++ b/src/mob.cpp @@ -65,8 +65,13 @@ void Page::createFromXML(XMLElement *e, World *w=nullptr) cId = e->StrAttribute("cid"); cValue = e->StrAttribute("cvalue"); + + xmle = e; } +void Page::saveToXML(void) +{} + Door::Door(void) : Mob() { ridable = false; @@ -101,6 +106,9 @@ void Door::createFromXML(XMLElement *e, World *w=nullptr) loc.x = Xlocx; } +void Door::saveToXML(void) +{} + Cat::Cat(void) : Mob() { ridable = true; @@ -154,9 +162,23 @@ bool Cat::bindTex(void) void Cat::createFromXML(XMLElement *e, World *w=nullptr) { (void)w; - float Xlocx; - if (e->QueryFloatAttribute("x", &Xlocx) == XML_NO_ERROR) - loc.x = Xlocx; + float spawnc; + + if (e->QueryFloatAttribute("x", &spawnc) == XML_NO_ERROR) + loc.x = spawnc; + else + loc.x = e->FloatAttribute("spawnx"); + + if (e->QueryFloatAttribute("y", &spawnc) == XML_NO_ERROR) + loc.y = spawnc; + + xmle = e; +} + +void Cat::saveToXML(void) +{ + E_SAVE_COORDS; + xmle->SetAttribute("alive", alive); } Rabbit::Rabbit(void) : Mob() @@ -210,16 +232,27 @@ bool Rabbit::bindTex(void) void Rabbit::createFromXML(XMLElement *e, World *w=nullptr) { (void)w; - float Xlocx, Xhealth; - if (e->QueryFloatAttribute("x", &Xlocx) == XML_NO_ERROR) - loc.x = Xlocx; - if (e->QueryFloatAttribute("health", &Xhealth) == XML_NO_ERROR) - maxHealth = health = Xhealth; - if (e->QueryBoolAttribute("aggressive", &aggressive) != XML_NO_ERROR) { - aggressive = false; - } + float spawnc; xmle = e; + + if (e->QueryFloatAttribute("x", &spawnc) == XML_NO_ERROR) + loc.x = spawnc; + else + loc.x = e->FloatAttribute("spawnx"); + + if (e->QueryFloatAttribute("y", &spawnc) == XML_NO_ERROR) + loc.y = spawnc; + + E_LOAD_HEALTH; + + if (e->QueryBoolAttribute("aggressive", &aggressive) != XML_NO_ERROR) + aggressive = false; +} + +void Rabbit::saveToXML(void) +{ + E_SAVE_HEALTH; } Bird::Bird(void) : Mob() @@ -269,16 +302,26 @@ void Bird::createFromXML(XMLElement *e, World *w=nullptr) { (void)w; float Xlocx, Xhealth; - if (e->QueryFloatAttribute("x", &Xlocx) == XML_NO_ERROR) - loc.x = Xlocx; - if (e->QueryFloatAttribute("health", &Xhealth) == XML_NO_ERROR) - maxHealth = health = Xhealth; - if (e->QueryFloatAttribute("y", &initialY) != XML_NO_ERROR) - initialY = 300; + + xmle = e; + + if (e->QueryFloatAttribute("x", &Xlocx) == XML_NO_ERROR) + loc.x = Xlocx; + if (e->QueryFloatAttribute("y", &initialY) != XML_NO_ERROR) + initialY = 300; + + E_LOAD_HEALTH; + if (e->QueryBoolAttribute("aggressive", &aggressive) != XML_NO_ERROR) aggressive = false; } +void Bird::saveToXML(void) +{ + E_SAVE_COORDS; + E_SAVE_HEALTH; +} + Trigger::Trigger(void) : Mob() { ridable = false; @@ -351,6 +394,9 @@ void Trigger::createFromXML(XMLElement *e, World *w=nullptr) id = e->StrAttribute("id"); } +void Trigger::saveToXML(void) +{} + Mob::~Mob() { delete inv; diff --git a/src/world.cpp b/src/world.cpp index 11bd671..64dbfe0 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -93,6 +93,9 @@ static const float bgDraw[4][3]={ { 255, 255, 0.1 } }; +static std::string currentXMLRaw; +XMLDocument currentXMLDoc; + /* ---------------------------------------------------------------------------- ** Functions section ** --------------------------------------------------------------------------*/ @@ -1067,110 +1070,24 @@ getSTextureLocation(unsigned int index) const vec2 World:: getStructurePos(int index) { - if (build.empty()) + if (build.empty() || (unsigned)index >= build.size()) return vec2 {0, 0}; if (index < 0) return build.back()->loc; - else if ((unsigned)index >= build.size()) - return vec2 {0, 0}; return build[index]->loc; } -template<typename T> -void appVal(const T &x, std::string &str) -{ - str.append(std::to_string(static_cast<int>(x)) + "\n"); -} - /** * Saves world data to a file. */ -void World::save(void){ - std::string data; - std::string save = currentXML + ".dat"; - std::ofstream out (save, std::ios::out | std::ios::binary); - - std::cout << "Saving to " << save << " ..." << '\n'; - - // save npcs - for (auto &n : npc) { - appVal(n->dialogIndex, data); - appVal(n->loc.x, data); - appVal(n->loc.y, data); - } - - // save structures - for (auto &b : build) { - appVal(b->loc.x, data); - appVal(b->loc.y, data); - } - - // save mobs - for (auto &m : mob) { - appVal(m->loc.x, data); - appVal(m->loc.y, data); - appVal(m->isAlive(), data); - } - - // wrap up - data.append("dOnE\0"); - out.write(data.data(), data.size()); - out.close(); -} - -template<typename T> -bool getVal(T &x, std::istringstream &iss) +void World::save(void) { - std::string str; - std::getline(iss, str); + for (const auto &e : entity) + e->saveToXML(); - if (str == "dOnE") - return false; - - x = std::stoi(str); - return true; -} - -void World::load(void){ - std::string save, data, line; - const char *filedata; - - save = currentXML + ".dat"; - filedata = readFile(save.c_str()); - data = filedata; - std::istringstream iss (data); - - for(auto &n : npc){ - if (!getVal(n->dialogIndex, iss)) return; - if (n->dialogIndex != 9999) - n->addAIFunc(false); - - if (!getVal(n->loc.x, iss)) return; - if (!getVal(n->loc.y, iss)) return; - } - - for(auto &b : build){ - if (!getVal(b->loc.x, iss)) return; - if (!getVal(b->loc.y, iss)) return; - } - - bool alive = true; - for(auto &m : mob){ - if (!getVal(m->loc.x, iss)) return; - if (!getVal(m->loc.y, iss)) return; - if (!getVal(alive, iss)) return; - if (!alive) - m->die(); - } - - while (std::getline(iss,line)) { - if(line == "dOnE") - break; - } - - delete[] filedata; + currentXMLDoc.SaveFile(currentXML.c_str(), false); } /** @@ -1893,18 +1810,6 @@ World *loadWorldFromPtr(World *ptr) * Loads a world from the given XML file. */ -static std::string currentXMLRaw; -XMLDocument currentXMLDoc; - -const XMLDocument& loadWorldXML(void) -{ - static XMLDocument xml; - if (xml.Parse(currentXMLRaw.data()) != XML_NO_ERROR) - UserError("XML Error: Failed to parse file (not your fault though..?)"); - - return xml; -} - World * loadWorldFromXMLNoSave(std::string path) { XMLDocument *_currentXMLDoc; @@ -2196,12 +2101,6 @@ loadWorldFromXMLNoSave(std::string path) { if (!loadedLeft && !loadedRight) { currentXML = _currentXML; currentXMLRaw = _currentXMLRaw; - - std::ifstream dat ((_currentXML + ".dat").data()); - if (dat.good()) { - dat.close(); - tmp->load(); - } } else { delete _currentXMLDoc; } diff --git a/xml/playerSpawnHill1.xml b/xml/playerSpawnHill1.xml index 0f19f9a..fef154b 100644 --- a/xml/playerSpawnHill1.xml +++ b/xml/playerSpawnHill1.xml @@ -5,19 +5,19 @@ <link right="playerSpawnHill2.xml"/> <time>12000</time> <hill peakx="0" peaky="1000" width="50"/> - <rabbit x="300" aggressive="false" health="100"/> - <bird y="500"/> - <cat/> + <rabbit spawnx="300" aggressive="false" maxHealth="100" health="32"/> + <bird spawny="500" x="379.1998" y="254.95029" health="1"/> + <cat x="0" y="67.996956" alive="1"/> <!--<trigger x="-300" id="Test"/>--> - <npc name="Ralph" hasDialog="true" x="300"/> - <npc name="Johnny" hasDialog="false" x="300"/> - <npc name="Big Dave" hasDialog="true" x="300"/> - <page x="-200" id="assets/pages/gootaGoFast.png" cid="canSprint" cvalue="1"/> - <page x="-500" id="assets/pages/gootaJump.png" cid="canJump" cvalue="1"/> + <npc name="Ralph" hasDialog="true" spawnx="300" health="1" x="-96.279839" y="66.496941" dindex="2"/> + <npc name="Johnny" hasDialog="false" spawnx="300" health="1" x="824.5191" y="71.996918" dindex="0"/> + <npc name="Big Dave" hasDialog="true" spawnx="300" health="1" x="235.77779" y="63.396919" dindex="9999"/> + <page spawnx="-200" id="assets/pages/gootaGoFast.png" cid="canSprint" cvalue="1"/> + <page spawnx="-500" id="assets/pages/gootaJump.png" cid="canJump" cvalue="1"/> <village name="Big Dave's bagel emporium! The greatest place on earth!"> - <structure type="0" x="-300" inside="playerSpawnHill1_Building1.xml"/> - <structure type="5" x="-500"/> - <stall type="market" texture="assets/style/classic/stall.png"> + <structure type="0" spawnx="-300" inside="playerSpawnHill1_Building1.xml" alive="1"/> + <structure type="5" spawnx="-500" alive="1"/> + <stall type="market" texture="assets/style/classic/stall.png" alive="1"> <text> <greet>Welcome to Smithy's! What would you like to purchase today?</greet> <accept>Thanks!</accept> @@ -38,14 +38,14 @@ And it wasn't stormy. <Dialog name="Ralph"> <text id="0" nextid="1"> Hello there! My name is Ralph. - <gotox>300</gotox> + <gotox>300</gotox> </text> <text id="1" nextid="2" call="Johnny" callid="0" pause="true"> You should go talk to my friend Johnny. He's a pretty chill dude. </text> <text id="2"> Niice. - <quest check="Your First Quest" fail="3"/></text> + <quest check="Your First Quest" fail="3"/></text> <text id="3"> Go check out Johnny. He's cool. </text> @@ -54,7 +54,7 @@ And it wasn't stormy. <Dialog name="Johnny"> <text id="0" nextid="1" pause="true"> Sup bro! Have a quest. To complete it, just go talk to Ralph again. - <quest assign="Your First Quest"> + <quest assign="Your First Quest"> Dank MayMay,2 Wood Sword,1 </quest> @@ -68,9 +68,5 @@ And it wasn't stormy. <text id="0" pause="true"> Hey friend! It's dangerous out there, here take these! Wait, promise you'll stop by my stand in the local market! - <give id="Wood Sword" count="1"/> - <give id="Hunters Bow" count="1"/> - <give id="Crude Arrow" count="110"/> - <give id="Fried Chicken" count="1"/> - </text> + <give id="Wood Sword" count="1"/> <give id="Hunters Bow" count="1"/> <give id="Crude Arrow" count="110"/> <give id="Fried Chicken" count="1"/></text> </Dialog> |