From b22860234ff7991c851211042a9832d88ccbb958 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Tue, 31 May 2016 08:49:48 -0400 Subject: entitys can modify xml --- src/common.cpp | 33 ++++++++ src/entities.cpp | 132 +++++++++++++++++------------ src/mob.cpp | 25 ++++-- src/ui.cpp | 4 +- src/world.cpp | 250 +++++++++++++++++++++++++++++-------------------------- 5 files changed, 265 insertions(+), 179 deletions(-) (limited to 'src') diff --git a/src/common.cpp b/src/common.cpp index c643174..bb1ad1e 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -174,6 +174,39 @@ const char *readFile(const char *path) return buf; } +std::string readFile(const std::string& path) +{ + std::ifstream in (path, std::ios::in); + std::string buffer; + + if (!in.is_open()) + UserError("Error reading file " + path); + + in.seekg(0, in.end); + buffer.reserve(in.tellg()); + in.seekg(0, in.beg); + in.read(&buffer[0], buffer.size()); + + in.close(); + return buffer; +} + +std::vector readFileA(const std::string& path) +{ + std::ifstream in (path, std::ios::in); + std::vector lines; + std::string line; + + if (!in.is_open()) + UserError("Error reading file " + path); + + while(std::getline(in, line)) + lines.push_back(line); + + in.close(); + return lines; +} + void UserError(std::string reason) { std::cout << "User error: " << reason << "!\n"; diff --git a/src/entities.cpp b/src/entities.cpp index 550748a..18c91ed 100644 --- a/src/entities.cpp +++ b/src/entities.cpp @@ -15,6 +15,7 @@ extern World *currentWorld; // main.cpp extern unsigned int loops; // main.cpp extern std::string xmlFolder; +extern XMLDocument currentXMLDoc; // a dynamic array of pointers to the NPC's that are being assigned the preloads std::vector aipreload; @@ -24,52 +25,17 @@ const unsigned int PLAYER_INV_SIZE = 43; // the size of an NPC's inventory const unsigned int NPC_INV_SIZE = 3; -static const unsigned int RAND_DIALOG_COUNT = 14; -const char *randomDialog[RAND_DIALOG_COUNT] = { - "What a beautiful day it is.", - "Have you ever went fast? I have.", - "I heard if you complete a quest, you'll get a special reward.", - "How much wood could a woodchuck chuck if a woodchuck could chuck wood?", - "I don\'t think anyone has ever been able to climb up that hill.", - "If you ever see a hole in the ground, watch out; it could mean the end for you.", - "Did you know this game has over 5000 lines of code? I didn\'t. I didn't even know I was in a game until now...", - "HELP MY CAPS LOCK IS STUCK", - "You know, if anyone ever asked me who I wanted to be when I grow up, I would say Abby Ross.", - "I want to have the wallpaper in our house changed. It doesn\'t really fit the environment.", - "Frig.", - "The sine of theta equals the opposite over the hdaypotenuese.", - "Did you know the developers spelt brazier as brazzier.", - "What's a bagel? I don't know because I'm mormon" -}; - -void randGetomName(Entity *e) -{ - unsigned int tempNum,max=0; - char *bufs; - - std::ifstream names ("assets/names_en-us",std::ios::in); - - names.seekg(0,names.beg); - - bufs = new char[32]; - - for(;!names.eof();max++) - names.getline(bufs,32); +static std::vector randomDialog (readFileA("assets/dialog_en-us")); - tempNum = rand() % max; - names.seekg(0,names.beg); - - for(unsigned int i=0;igender = (bufs[0] == 'm') ? MALE : FEMALE; - - strcpy(e->name, bufs + 1); + e->gender = (name[0] == 'm') ? MALE : FEMALE; - delete[] bufs; + e->name = &name[1]; } Entity::Entity(void) @@ -101,7 +67,6 @@ Entity::Entity(void) hitDuration = maxHitDuration = 0; inv = nullptr; - name = nullptr; } // spawns the entity you pass to it based off of coords and global entity settings @@ -114,11 +79,10 @@ void Entity::spawn(float x, float y) health = maxHealth = 1; // generate a name - name = new char[32]; if (type == MOBT) - strncpy(name, "mob", 3); + name = "mob"; else - randGetomName(this); + getRandomName(this); setCooldown(0); } @@ -168,6 +132,11 @@ void Entity::die(void) { alive = false; health = 0; + + if (xmle) { + xmle->SetAttribute("alive", false); + currentXMLDoc.SaveFile(currentXML.c_str(), false); + } } bool Entity::isAlive(void) const @@ -218,7 +187,12 @@ Player::Player() : Entity() Player::~Player() { delete inv; - delete[] name; +} + +void Player::createFromXML(XMLElement *e, World *w=nullptr) +{ + (void)e; + (void)w; } NPC::NPC() : Entity() @@ -237,7 +211,7 @@ NPC::NPC() : Entity() tex = TextureIterator({"assets/NPC.png"}); inv = new Inventory(NPC_INV_SIZE); - randDialog = rand() % RAND_DIALOG_COUNT - 1; + randDialog = randGet() % randomDialog.size(); dialogIndex = 0; dialogCount = 0; @@ -249,7 +223,42 @@ NPC::NPC() : Entity() NPC::~NPC() { delete inv; - delete[] name; +} + +void NPC::createFromXML(XMLElement *e, World *w=nullptr) +{ + std::string npcname; + bool dialog; + float spawnx, Xhealth; + unsigned int flooor; + + // spawn at coordinates if desired + if (e->QueryFloatAttribute("x", &spawnx) == XML_NO_ERROR) + spawn(spawnx, 100); + else + spawn(0, 100); + + // name override + if (!(npcname = e->StrAttribute("name")).empty()) + name = npcname; + + // dialog enabling + dialog = false; + if (e->QueryBoolAttribute("hasDialog", &dialog) == XML_NO_ERROR && dialog) + addAIFunc(false); + else + dialogIndex = 9999; + + + if (/*Indoor && */e->QueryUnsignedAttribute("floor", &flooor) == XML_NO_ERROR) + Indoorp(w)->moveToFloor(this, flooor); + + // custom health value + if (e->QueryFloatAttribute("health", &Xhealth) == XML_NO_ERROR) { + health = maxHealth = Xhealth; + } + + xmle = e; } Merchant::Merchant() : NPC() @@ -283,8 +292,6 @@ Merchant::Merchant() : NPC() Merchant::~Merchant() { - //delete inv; - delete[] name; } Structures::Structures() : Entity() @@ -295,7 +302,19 @@ Structures::Structures() : Entity() Structures::~Structures() { - delete[] name; +} + +void Structures::createFromXML(XMLElement *e, World *w) +{ + float spawnx; + + inWorld = w; + inside = e->StrAttribute("inside"); + textureLoc = e->StrAttribute("texture"); + + spawn(static_cast(e->UnsignedAttribute("type")), + e->QueryFloatAttribute("x", &spawnx) == XML_NO_ERROR ? spawnx : (randGet() % w->getTheWidth() / 2.0f), + 100); } Object::Object() @@ -319,7 +338,12 @@ Object::Object(std::string in, std::string pd) Object::~Object() { - delete[] name; +} + +void Object::createFromXML(XMLElement *e, World *w=nullptr) +{ + (void)e; + (void)w; } void Object::reloadTexture(void) @@ -773,7 +797,7 @@ void Merchant::wander(int timeRun) { void Merchant::interact() { std::thread([this]{ - ui::merchantBox(name, trade[currTrade], ":Accept:Good-Bye", false, toSay->c_str()); + ui::merchantBox(name.c_str(), trade[currTrade], ":Accept:Good-Bye", false, toSay->c_str()); ui::waitForDialog(); // handle normal dialog options diff --git a/src/mob.cpp b/src/mob.cpp index d6df3fd..526d7b1 100644 --- a/src/mob.cpp +++ b/src/mob.cpp @@ -10,6 +10,7 @@ Mob::Mob(void) type = MOBT; inv = nullptr; rider = nullptr; + xmle = nullptr; canMove = true; loc = 0; } @@ -53,8 +54,9 @@ bool Page::bindTex(void) return true; } -void Page::createFromXML(const XMLElement *e) +void Page::createFromXML(XMLElement *e, World *w=nullptr) { + (void)w; float Xlocx; if (e->QueryFloatAttribute("x", &Xlocx) == XML_NO_ERROR) loc.x = Xlocx; @@ -91,8 +93,9 @@ bool Door::bindTex(void) return true; } -void Door::createFromXML(const XMLElement *e) +void Door::createFromXML(XMLElement *e, World *w=nullptr) { + (void)w; float Xlocx; if (e->QueryFloatAttribute("x", &Xlocx) == XML_NO_ERROR) loc.x = Xlocx; @@ -148,8 +151,9 @@ bool Cat::bindTex(void) return true; } -void Cat::createFromXML(const XMLElement *e) +void Cat::createFromXML(XMLElement *e, World *w=nullptr) { + (void)w; float Xlocx; if (e->QueryFloatAttribute("x", &Xlocx) == XML_NO_ERROR) loc.x = Xlocx; @@ -203,15 +207,19 @@ bool Rabbit::bindTex(void) return true; } -void Rabbit::createFromXML(const XMLElement *e) +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) + if (e->QueryBoolAttribute("aggressive", &aggressive) != XML_NO_ERROR) { aggressive = false; + } + + xmle = e; } Bird::Bird(void) : Mob() @@ -257,8 +265,9 @@ bool Bird::bindTex(void) return true; } -void Bird::createFromXML(const XMLElement *e) +void Bird::createFromXML(XMLElement *e, World *w=nullptr) { + (void)w; float Xlocx, Xhealth; if (e->QueryFloatAttribute("x", &Xlocx) == XML_NO_ERROR) loc.x = Xlocx; @@ -333,8 +342,9 @@ bool Trigger::bindTex(void) return false; } -void Trigger::createFromXML(const XMLElement *e) +void Trigger::createFromXML(XMLElement *e, World *w=nullptr) { + (void)w; float Xlocx; if (e->QueryFloatAttribute("x", &Xlocx) == XML_NO_ERROR) loc.x = Xlocx; @@ -344,7 +354,6 @@ void Trigger::createFromXML(const XMLElement *e) Mob::~Mob() { delete inv; - delete[] name; } extern World *currentWorld; diff --git a/src/ui.cpp b/src/ui.cpp index 7ae444c..5a7ada1 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -1408,7 +1408,9 @@ EXIT: if (debug) posFlag ^= true; else { - currentWorld->addStructure(FIRE_PIT, player->loc.x, player->loc.y, "", ""); + auto s = new Structures(); + s->spawn(FIRE_PIT, player->loc.x, player->loc.y); + currentWorld->addStructure(s); currentWorld->addLight({player->loc.x + SCREEN_WIDTH/2, player->loc.y},{1.0f,1.0f,1.0f}); //currentWorld->getLastLight()->follow(currentWorld->build.back()); currentWorld->getLastLight()->makeFlame(); diff --git a/src/world.cpp b/src/world.cpp index 2ecccec..f13c3b7 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -8,6 +8,7 @@ #include #include #include +#include // local game headers #include @@ -317,7 +318,7 @@ void World::drawBackgrounds(void) if (worldShade > 0) { auto xcoord = offset.x * 0.9f; - + for (auto &s : star) { *(si++) = s.x + xcoord; *(si++) = s.y, @@ -497,17 +498,17 @@ void World::draw(Player *p) pOffset = (offset.x + p->width / 2 - worldStart) / HLINE; // only draw world within player vision - iStart = static_cast(fmax(pOffset - (SCREEN_WIDTH / 2 / HLINE) - GROUND_HILLINESS, 0)); + iStart = std::clamp(static_cast(pOffset - (SCREEN_WIDTH / 2 / HLINE) - GROUND_HILLINESS), + 0, static_cast(lineCount)); iEnd = std::clamp(static_cast(pOffset + (SCREEN_WIDTH / 2 / HLINE)), - static_cast(GROUND_HILLINESS), - static_cast(worldData.size())); + 0, static_cast(lineCount)); // draw the dirt bgTex++; std::vector> c; for (int i = iStart; i < iEnd; i++) { - if (worldData[i].groundHeight <= 0) { + if (worldData[i].groundHeight <= 0) { // TODO holes (andy) worldData[i].groundHeight = GROUND_HEIGHT_MINIMUM - 1; glColor4ub(0, 0, 0, 255); } else { @@ -1069,6 +1070,9 @@ getSTextureLocation(unsigned int index) const vec2 World:: getStructurePos(int index) { + if (build.empty()) + return vec2 {0, 0}; + if (index < 0) return build.back()->loc; else if ((unsigned)index >= build.size()) @@ -1431,13 +1435,9 @@ WorldSwitchInfo World::goInsideStructure(Player *p) } void World:: -addStructure(BUILD_SUB sub, float x,float y, std::string tex, std::string inside) +addStructure(Structures *s) { - build.push_back(new Structures()); - build.back()->inWorld = this; - build.back()->textureLoc = tex; - build.back()->spawn(sub, x, y); - build.back()->inside = inside; + build.push_back(s); entity.push_back(build.back()); } @@ -1457,11 +1457,9 @@ void World::addMob(Mob *m, vec2 coord) } void World:: -addNPC(float x, float y) +addNPC(NPC *n) { - npc.push_back(new NPC()); - npc.back()->spawn(x, y); - + npc.push_back(n); entity.push_back(npc.back()); } @@ -1897,37 +1895,63 @@ 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; + XMLDocument *_currentXMLDoc; + std::string _currentXML, + _currentXMLRaw; + XMLElement *wxml; XMLElement *vil; World *tmp; - float spawnx, randx; - bool dialog,Indoor; - unsigned int flooor; + Entity *newEntity; + float spawnx; + bool Indoor; const char *ptr; std::string name, sptr; // no file? -> no world if (path.empty()) - return NULL; + return nullptr; - currentXML = std::string(xmlFolder + path); - currentXMLDoc.LoadFile(currentXML.c_str()); + _currentXML = xmlFolder + path; + _currentXMLRaw = readFile(_currentXML.c_str()); + + // create a temporary XMLDocument if this isn't the main world + if (!loadedLeft && !loadedRight) + _currentXMLDoc = ¤tXMLDoc; + else + _currentXMLDoc = new XMLDocument(); + + // parse the file + if (_currentXMLDoc->Parse(_currentXMLRaw.data()) != XML_NO_ERROR) + UserError("XML Error: Failed to parse file (not your fault though..?)"); // attempt to load a tag - if ((wxml = currentXMLDoc.FirstChildElement("World"))) { + if ((wxml = _currentXMLDoc->FirstChildElement("World"))) { wxml = wxml->FirstChildElement(); - vil = currentXMLDoc.FirstChildElement("World")->FirstChildElement("village"); + vil = _currentXMLDoc->FirstChildElement("World")->FirstChildElement("village"); tmp = new World(); Indoor = false; } // attempt to load an tag - else if ((wxml = currentXMLDoc.FirstChildElement("IndoorWorld"))) { + else if ((wxml = _currentXMLDoc->FirstChildElement("IndoorWorld"))) { wxml = wxml->FirstChildElement(); vil = NULL; tmp = new IndoorWorld(); @@ -1936,10 +1960,11 @@ XMLDocument currentXMLDoc; // error: can't load a world... else - UserError("XML Error: Cannot find a or tag in " + currentXML + "!"); + UserError("XML Error: Cannot find a or tag in " + _currentXML + "!"); // iterate through world tags while (wxml) { + newEntity = nullptr; name = wxml->Name(); // world linkage @@ -1951,10 +1976,12 @@ XMLDocument currentXMLDoc; // load the left world if it isn't if (!loadedLeft) { - loadedLeft = true; + loadedRight = true; currentWorldToLeft = loadWorldFromXMLNoSave(ptr); - loadedLeft = false; - } + loadedRight = false; + } else { + currentWorldToLeft = nullptr; + } } // links world to the right @@ -1963,10 +1990,12 @@ XMLDocument currentXMLDoc; // load the right world if it isn't if (!loadedRight) { - loadedRight = true; + loadedLeft = true; currentWorldToRight = loadWorldFromXMLNoSave(ptr); - loadedRight = false; - } + loadedLeft = false; + } else { + currentWorldToRight = nullptr; + } } // tells what world is outside, if in a structure @@ -1975,7 +2004,7 @@ XMLDocument currentXMLDoc; // error, invalid link tag else - UserError("XML Error: Invalid tag in " + currentXML + "!"); + UserError("XML Error: Invalid tag in " + _currentXML + "!"); } @@ -1985,9 +2014,10 @@ XMLDocument currentXMLDoc; tmp->setStyle(wxml->StrAttribute("folder")); // set background folder - if (wxml->QueryUnsignedAttribute("background", &flooor) != XML_NO_ERROR) - UserError("XML Error: No background given in