diff options
-rw-r--r-- | Changelog | 17 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | assets/blankNormal.png | bin | 0 -> 172 bytes | |||
-rw-r--r-- | assets/cat_normal.png | bin | 0 -> 820 bytes | |||
-rw-r--r-- | assets/cat_normal_old.png | bin | 0 -> 684 bytes | |||
-rw-r--r-- | assets/dialog_en-us | 15 | ||||
-rw-r--r-- | assets/items/basic_torch.png | bin | 0 -> 317 bytes | |||
-rw-r--r-- | assets/style/classic/bg/bgnew.png | bin | 0 -> 821843 bytes | |||
-rw-r--r-- | assets/style/classic/bg/star.png | bin | 0 -> 731 bytes | |||
-rw-r--r-- | include/common.hpp | 2 | ||||
-rw-r--r-- | include/coolarray.hpp | 113 | ||||
-rw-r--r-- | include/entities.hpp | 145 | ||||
-rw-r--r-- | include/mob.hpp | 14 | ||||
-rw-r--r-- | include/world.hpp | 23 | ||||
-rw-r--r-- | main.cpp | 102 | ||||
-rw-r--r-- | src/common.cpp | 33 | ||||
-rw-r--r-- | src/entities.cpp | 146 | ||||
-rw-r--r-- | src/mob.cpp | 25 | ||||
-rw-r--r-- | src/ui.cpp | 6 | ||||
-rw-r--r-- | src/ui_action.cpp | 2 | ||||
-rw-r--r-- | src/world.cpp | 303 | ||||
-rwxr-xr-x | win32/main.exe | bin | 6027539 -> 6226815 bytes | |||
-rw-r--r-- | xml/playerSpawnHill1.xml | 96 |
23 files changed, 655 insertions, 389 deletions
@@ -1018,3 +1018,20 @@ - fixed grass squishing - player sits on cat better - world shading is good-er + +5/31/2016: +========== + + - fixed name generation-er + - move random dialogs to file + - entitys can modify their XMLs + - 'alive' XML attribute works + - lighting's pretty neat + +6/3/2016: +========= + + - majorly improved particle handling, made CoolArray + - found bugs in quest handling... + - making lights and stars n stuff goood + - story??? art??? music??? @@ -12,7 +12,7 @@ ifeq ($(TARGET_OS),win32) -lSDL2main -lSDL2 -lSDL2_image -lSDL2_mixer -lfreetype endif -CXXFLAGS = -g -m$(TARGET_BITS) -std=c++14 +CXXFLAGS = -g -m$(TARGET_BITS) -std=c++14 -fext-numeric-literals CXXINC = -Iinclude -Iinclude/freetype CXXWARN = -Wall -Wextra -Werror #-pedantic-errors diff --git a/assets/blankNormal.png b/assets/blankNormal.png Binary files differnew file mode 100644 index 0000000..cff3ee7 --- /dev/null +++ b/assets/blankNormal.png diff --git a/assets/cat_normal.png b/assets/cat_normal.png Binary files differnew file mode 100644 index 0000000..59aaee8 --- /dev/null +++ b/assets/cat_normal.png diff --git a/assets/cat_normal_old.png b/assets/cat_normal_old.png Binary files differnew file mode 100644 index 0000000..c3ed4aa --- /dev/null +++ b/assets/cat_normal_old.png diff --git a/assets/dialog_en-us b/assets/dialog_en-us new file mode 100644 index 0000000..dfe7b03 --- /dev/null +++ b/assets/dialog_en-us @@ -0,0 +1,15 @@ +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 hypotenuese. +Did you know the developers spelt brazier as brazzier. +What's a bagel? I don't know because I'm mormon + diff --git a/assets/items/basic_torch.png b/assets/items/basic_torch.png Binary files differnew file mode 100644 index 0000000..fe6a994 --- /dev/null +++ b/assets/items/basic_torch.png diff --git a/assets/style/classic/bg/bgnew.png b/assets/style/classic/bg/bgnew.png Binary files differnew file mode 100644 index 0000000..05c352b --- /dev/null +++ b/assets/style/classic/bg/bgnew.png diff --git a/assets/style/classic/bg/star.png b/assets/style/classic/bg/star.png Binary files differnew file mode 100644 index 0000000..6360d30 --- /dev/null +++ b/assets/style/classic/bg/star.png diff --git a/include/common.hpp b/include/common.hpp index 1ef8b8a..f7507cb 100644 --- a/include/common.hpp +++ b/include/common.hpp @@ -266,6 +266,8 @@ void strVectorSortAlpha(std::vector<std::string> *v); // reads the given file into a buffer and returns a pointer to the buffer const char *readFile(const char *path); +std::string readFile(const std::string& path); +std::vector<std::string> readFileA(const std::string& path); // aborts the program, printing the given error void UserError(std::string reason); diff --git a/include/coolarray.hpp b/include/coolarray.hpp new file mode 100644 index 0000000..3e167b7 --- /dev/null +++ b/include/coolarray.hpp @@ -0,0 +1,113 @@ +#ifndef COOLARRAY_H_ +#define COOLARRAY_H_ + +#include <memory> +#include <initializer_list> + +template<class T> +class CoolArray { +private: + T *buffer; + size_t _size, _capacity; +public: + CoolArray(void) { + buffer = nullptr; + _size = 0; + _capacity = 0; + } + + CoolArray(size_t n, const T& value) { + buffer = new T[n]; + _size = n; + _capacity = n; + std::fill(buffer, buffer + _size, value); + } + + ~CoolArray(void) { + delete[] buffer; + } + + T& operator[](size_t idx) { + return buffer[idx]; + } + + void operator=(std::initializer_list<T> a) { + if (buffer != nullptr) + delete[] buffer; + + _size = a.size(); + buffer = new T[_size]; + _capacity = _size; + std::copy(a.begin(), a.end(), buffer); + } + + template<class Func> + void remove_if(Func f) { + for (size_t i = 0; i < _size; ++i) { + if (f(buffer[i])) + std::move(buffer + i + 1, buffer + _size--, buffer + i); + } + } + + void reserve(size_t n) { + if (buffer != nullptr) { + T *newbuf = new T[n]; + std::copy(buffer, buffer + (_size < n ? _size : n), newbuf); + _capacity = n; + delete[] buffer; + buffer = newbuf; + } else { + buffer = new T[n]; + _capacity = n; + } + } + + void resize(size_t n) { + reserve(n); + _size = n; + } + + void clear(void) { + delete[] buffer; + _size = 0; + _capacity = 0; + } + + size_t size(void) const { + return _size; + } + + size_t capacity(void) const { + return _capacity; + } + + T& front(void) { + return buffer[0]; + } + + T& back(void) { + return buffer[_size - 1]; + } + + T* begin(void) { + return buffer; + } + + T* end(void) { + return buffer + _size; + } + + void push_back(const T& x) { + if (_size >= _capacity) + reserve(_capacity + 5); + + buffer[_size++] = x; + } + + void pop_back(void) { + --_size; + } +}; + + +#endif // COOLARRAY_H_ diff --git a/include/entities.hpp b/include/entities.hpp index d2185c4..7c712c9 100644 --- a/include/entities.hpp +++ b/include/entities.hpp @@ -17,6 +17,10 @@ #include <inventory.hpp> #include <texture.hpp> +// local library includes +#include <tinyxml2.h> +using namespace tinyxml2; + /* ---------------------------------------------------------------------------- ** Structures section ** --------------------------------------------------------------------------*/ @@ -103,64 +107,6 @@ extern const unsigned int NPC_INV_SIZE; class World; /** - * The particle class, handles a single particle. - */ -class Particles{ -public: - // the location of the particle - vec2 loc; - float zOffset; - - // the width of the particle, in pixels - float width; - - // the height of the particle, in pixels - float height; - - // the velocity of the particle, in pixels - vec2 vel; - - // the color of the particle - Color color; - - // TODO - vec2 index; - - // the amount of milliseconds left for the particle to live - float duration; - - // when true, the particle will move - bool canMove; - - // TODO - bool fountain; - - // when true, the particle will be affected by gravity - bool gravity; - - // when true, draws the particle behind structures - bool behind; - - // when true, the particle will bounce on impact with ground - bool bounce; - - // creates a particle with the desired characteristics - Particles(float x, float y, float w, float h, float vx, float vy, Color c, float d); - - // allows the particle to be destroyed - ~Particles(void){} - - // draws the particle - void draw(GLfloat*& p) const; - - // updates a particle - void update(float _gravity, float ground_y); - - // returns true if the particle should be killed - bool kill(float delta); -}; - -/** * The entity class. * This class contains common functions and variables for all types of * entities, i.e. a common structure. @@ -187,6 +133,10 @@ protected: // the max cooldown display float maxHitDuration; + + // the entity's XML element, for saving/loading stuff + XMLElement *xmle; + public: // contains the entity's coordinates, in pixels vec2 loc; @@ -235,7 +185,7 @@ public: int subtype; // the entity's name, randomly generated on spawn - char *name; + std::string name; // the entity's gender GENDER gender; @@ -289,6 +239,9 @@ public: // returns true if the coordinate is within the entity bool isInside(vec2 coord) const; + // constructs the entity with an XML thing-thang + virtual void createFromXML(XMLElement *e, World *w=nullptr) =0; + // a common constructor, clears variables Entity(void); @@ -296,7 +249,7 @@ public: virtual ~Entity(){} }; -class Player : public Entity{ +class Player : public Entity { public: Entity *ride; QuestHandler qh; @@ -305,9 +258,10 @@ public: ~Player(); void save(void); void sspawn(float x,float y); + void createFromXML(XMLElement *e, World *w); }; -class Structures : public Entity{ +class Structures : public Entity { public: BUILD_SUB bsubtype; World *inWorld; @@ -318,6 +272,7 @@ public: ~Structures(); unsigned int spawn(BUILD_SUB, float, float); + void createFromXML(XMLElement *e, World *w); }; @@ -340,6 +295,7 @@ public: virtual void interact(); virtual void wander(int); + void createFromXML(XMLElement *e, World *w); }; class Merchant : public NPC { @@ -379,8 +335,9 @@ public: void interact(void); bool operator==(const Object &o) { - return !strcmp(name, o.name) && (loc == o.loc); + return (name == o.name) && (loc == o.loc); } + void createFromXML(XMLElement *e, World *w); }; /** @@ -422,6 +379,70 @@ public: { flame = true; } + + void createFromXML(XMLElement *e); +}; + +/** + * The particle class, handles a single particle. + */ +class Particles{ +public: + // the location of the particle + vec2 loc; + float zOffset; + + // the width of the particle, in pixels + float width; + + // the height of the particle, in pixels + float height; + + // the velocity of the particle, in pixels + vec2 vel; + + // the color of the particle + Color color; + + // TODO + vec2 index; + + // the amount of milliseconds left for the particle to live + float duration; + + // when true, the particle will move + bool canMove; + + // TODO + bool fountain; + + // when true, the particle will be affected by gravity + bool gravity; + + // when true, draws the particle behind structures + bool behind; + + // when true, the particle will bounce on impact with ground + bool bounce; + + Structures *stu; + + Particles(void){} + + // creates a particle with the desired characteristics + Particles(float x, float y, float w, float h, float vx, float vy, Color c, float d); + + // allows the particle to be destroyed + ~Particles(void){} + + // draws the particle + void draw(GLfloat*& p) const; + + // updates a particle + void update(float _gravity, float ground_y); + + // returns true if the particle should be killed + bool timeUp(void); }; #include <mob.hpp> diff --git a/include/mob.hpp b/include/mob.hpp index 4425159..450cf69 100644 --- a/include/mob.hpp +++ b/include/mob.hpp @@ -20,6 +20,7 @@ using Drop = std::tuple<std::string, unsigned int, float>; class Mob : public Entity { protected: + XMLElement *xmle; std::forward_list<Drop> drop; unsigned int actCounter; @@ -41,7 +42,6 @@ public: virtual void onDeath(void); virtual bool bindTex(void) =0; - virtual void createFromXML(const XMLElement *e) =0; }; constexpr Mob *Mobp(Entity *e) { @@ -59,7 +59,7 @@ public: void act(void); void onHit(unsigned int); bool bindTex(void); - void createFromXML(const XMLElement *e); + void createFromXML(XMLElement *e, World *w) final; }; class Door : public Mob { @@ -69,7 +69,7 @@ public: void act(void); void onHit(unsigned int); bool bindTex(void); - void createFromXML(const XMLElement *e); + void createFromXML(XMLElement *e, World *w) final; }; class Cat : public Mob { @@ -79,7 +79,7 @@ public: void act(void); void onHit(unsigned int); bool bindTex(void); - void createFromXML(const XMLElement *e); + void createFromXML(XMLElement *e, World *w) final; }; class Rabbit : public Mob { @@ -89,7 +89,7 @@ public: void act(void); void onHit(unsigned int); bool bindTex(void); - void createFromXML(const XMLElement *e); + void createFromXML(XMLElement *e, World *w) final; }; class Bird : public Mob { @@ -101,7 +101,7 @@ public: void act(void); void onHit(unsigned int); bool bindTex(void); - void createFromXML(const XMLElement *e); + void createFromXML(XMLElement *e, World *w) final; }; class Trigger : public Mob { @@ -114,7 +114,7 @@ public: void act(void); void onHit(unsigned int); bool bindTex(void); - void createFromXML(const XMLElement *e); + void createFromXML(XMLElement *e, World *w) final; }; #endif // MOB_H_ diff --git a/include/world.hpp b/include/world.hpp index ecfa14f..8c241a9 100644 --- a/include/world.hpp +++ b/include/world.hpp @@ -9,13 +9,14 @@ // local game includes #include <common.hpp> #include <entities.hpp> +#include <coolarray.hpp> /** * The background type enum. * This enum contains all different possibilities for world backgrounds; used * in World::setBackground() to select the appropriate images. */ -enum class WorldBGType : unsigned char { +enum class WorldBGType : unsigned int { Forest, /**< A forest theme. */ WoodHouse /**< An indoor wooden house theme. */ }; @@ -256,7 +257,7 @@ protected: * * @see addParticle() */ - std::vector<Particles> particles; + CoolArray<Particles> particles; /** * A vector of all structures in the world. @@ -465,14 +466,14 @@ public: void addMob(Mob *m, vec2 coord); - void addNPC(float x, float y); + void addNPC(NPC *n); void addObject(std::string in, std::string pickupDialog, float x, float y); void addParticle(float x, float y, float w, float h, float vx, float vy, Color color, int dur); void addParticle(float x, float y, float w, float h, float vx, float vy, Color color, int dur, unsigned char flags); - void addStructure(BUILD_SUB subtype, float x, float y, std::string tex, std::string inside); + void addStructure(Structures *s); Village *addVillage(std::string name, World *world); }; @@ -549,6 +550,12 @@ public: }; /** + * Constructs an XML object for accessing/modifying the current world's XML + * file. + */ +const XMLDocument& loadWorldXML(void); + +/** * Loads the player into the world created by the given XML file. If a world is * already loaded it will be saved before the transition is made. */ @@ -560,8 +567,16 @@ World *loadWorldFromXML(std::string path); */ World *loadWorldFromXMLNoSave(std::string path); +/** + * Loads a world using a pointer to the current world (used for loading adjacent + * worlds that have already been read into memory. + */ World *loadWorldFromPtr(World *ptr); +/** + * Casts a normal world to an indoor world, to access IndoorWorld-exclusive + * elements. + */ constexpr IndoorWorld *Indoorp(World *w) { return (IndoorWorld *)w; @@ -25,7 +25,7 @@ using namespace tinyxml2; ** --------------------------------------------------------------------------*/ // the game's window title name -constexpr const char *GAME_NAME = "Independent Study v0.7 alpha - NOW WITH lights and snow and stuff"; +constexpr const char *GAME_NAME = "Independent Study v0.8 alpha - NOW WITH decent shaders"; // SDL's window object SDL_Window *window = NULL; @@ -93,6 +93,15 @@ GLuint mouseTex; // the center of the screen vec2 offset; +/* + * fps contains the game's current FPS, debugY contains the player's + * y coordinates, updated at a certain interval. These are used in + * the debug menu (see below). + */ + +static unsigned int fps=0; +static float debugY=0; + // handles all logic operations void logic(void); @@ -229,33 +238,38 @@ int main(int argc, char *argv[]){ // load mouse texture, and other inventory textures mouseTex = Texture::loadTexture("assets/mouse.png"); - // read in all XML file names in the folder - std::vector<std::string> xmlFiles; + // spawn the player + player = new Player(); + player->sspawn(0,100); + + // get a world if (xmlFolder.empty()) xmlFolder = "xml/"; - if (getdir(std::string("./" + xmlFolder).c_str(), xmlFiles)) - UserError("Error reading XML files!!!"); - - // alphabetically sort files - strVectorSortAlpha(&xmlFiles); - - // load the first valid XML file for the world - for (const auto &xf : xmlFiles) { - if (xf[0] != '.' && strcmp(&xf[xf.size() - 3], "dat")){ - // read it in - std::cout << "File to load: " << xf << '\n'; - currentWorld = loadWorldFromXML(xf); - break; + + 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!!!"); + + // alphabetically sort files + strVectorSortAlpha(&xmlFiles); + + // load the first valid XML file for the world + for (const auto &xf : xmlFiles) { + if (xf[0] != '.' && strcmp(&xf[xf.size() - 3], "dat")){ + // read it in + std::cout << "File to load: " << xf << '\n'; + currentWorld = loadWorldFromXML(xf); + break; + } } } // make sure the world was made - if (currentWorld == NULL) + if (currentWorld == nullptr) UserError("Plot twist: The world never existed...?"); - // spawn the player - player = new Player(); - player->sspawn(0,100); ui::menu::init(); currentWorld->bgmPlay(nullptr); @@ -268,12 +282,26 @@ int main(int argc, char *argv[]){ // the main loop, in all of its gloriousness.. gameRunning = true; std::thread([&]{ - while (gameRunning) + while (gameRunning) { mainLoop(); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + }).detach(); + + // the debug loop, gets debug screen values + std::thread([&]{ + while (gameRunning) { + fps = 1000 / game::time::getDeltaTime(); + debugY = player->loc.y; + + std::this_thread::sleep_for(std::chrono::seconds(1)); + } }).detach(); - while (gameRunning) + while (gameRunning) { render(); + ui::handleEvents(); + } // put away the brice for later game::briceSave(); @@ -297,41 +325,21 @@ int main(int argc, char *argv[]){ return 0; // Calls everything passed to atexit } -/* - * fps contains the game's current FPS, debugY contains the player's - * y coordinates, updated at a certain interval. These are used in - * the debug menu (see below). - */ - -static unsigned int fps=0; -static float debugY=0; - void mainLoop(void){ - static unsigned int debugDiv=0; // A divisor used to update the debug menu if it's open - game::time::mainLoopHandler(); if (currentMenu) { return; } else { // handle keypresses - currentWorld could change here - ui::handleEvents(); + //ui::handleEvents(); if (game::time::tickHasPassed()) logic(); currentWorld->update(player, game::time::getDeltaTime(), game::time::getTickCount()); currentWorld->detect(player); - - if (++debugDiv == 20) { - debugDiv=0; - - fps = 1000 / game::time::getDeltaTime(); - debugY = player->loc.y; - } } - - SDL_Delay(1); } void render() { @@ -352,10 +360,10 @@ void render() { offset.y = std::max(player->loc.y + player->height / 2, SCREEN_HEIGHT / 2.0f); // "setup" - glm::mat4 projection = glm::ortho( static_cast<float>(floor(offset.x-SCREEN_WIDTH/2)), //left - static_cast<float>(floor(offset.x+SCREEN_WIDTH/2)), //right - static_cast<float>(floor(offset.y-SCREEN_HEIGHT/2)), //bottom - static_cast<float>(floor(offset.y+SCREEN_HEIGHT/2)), //top + glm::mat4 projection = glm::ortho( floor(offset.x-SCREEN_WIDTH/2), //left + floor(offset.x+SCREEN_WIDTH/2), //right + floor(offset.y-SCREEN_HEIGHT/2), //bottom + floor(offset.y+SCREEN_HEIGHT/2), //top 10.0f, //near -10.0f); //far 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<std::string> readFileA(const std::string& path) +{ + std::ifstream in (path, std::ios::in); + std::vector<std::string> 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..f59b462 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<NPC *> 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<std::string> randomDialog (readFileA("assets/dialog_en-us")); - tempNum = rand() % max; - names.seekg(0,names.beg); - - for(unsigned int i=0;i<tempNum;i++) - names.getline(bufs,32); - - names.close(); +void getRandomName(Entity *e) +{ + auto names = readFileA("assets/names_en-us"); + auto name = names[randGet() % names.size()]; // gender is a binary construct - e->gender = (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<BUILD_SUB>(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 @@ -917,11 +941,12 @@ Particles::Particles(float x, float y, float w, float h, float vx, float vy, Col bounce = false; index = Texture::getIndex(c); zOffset = ((rand()%20)-10)/1000.0f; + stu = nullptr; } void Particles::draw(GLfloat*& p) const { - vec2 tc = vec2(0.25f * this->index.x, 0.125f * (8.0f - this->index.y)); + vec2 tc = vec2(0.25f * index.x, 0.125f * (8.0f - index.y)); float z = 0.9; if (behind) @@ -980,6 +1005,8 @@ void Particles::draw(GLfloat*& p) const void Particles::update(float _gravity, float ground_y) { + auto delta = game::time::getDeltaTime(); + // handle ground collision if (loc.y < ground_y) { loc.y = ground_y; @@ -996,13 +1023,16 @@ void Particles::update(float _gravity, float ground_y) // handle gravity else if (gravity && vel.y > -1.0f) { - vel.y -= _gravity * game::time::getDeltaTime(); + vel.y -= _gravity * delta; } + + // handle lifetime + duration -= delta; } -bool Particles::kill(float delta) +bool Particles::timeUp(void) { - return (duration -= delta) <= 0; + return !(duration > 0); } void Player::save(void) { diff --git a/src/mob.cpp b/src/mob.cpp index a0e7087..1bc1499 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; @@ -1152,7 +1152,7 @@ EXIT: toggleBlackFast(); player->canMove = true; }; - + while(SDL_PollEvent(&e)) { switch(e.type) { @@ -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}, 400.0f, {1.0f,1.0f,1.0f}); //currentWorld->getLastLight()->follow(currentWorld->build.back()); currentWorld->getLastLight()->makeFlame(); diff --git a/src/ui_action.cpp b/src/ui_action.cpp index ebdc705..9029907 100644 --- a/src/ui_action.cpp +++ b/src/ui_action.cpp @@ -124,7 +124,7 @@ void actionAttack(void) ui::toggleWhiteFast(); } } else { - ui::dialogBox(player->name, "", false, "%s doesn't appear to be in the mood for fighting...", m->name); + ui::dialogBox(player->name, "", false, "%s doesn't appear to be in the mood for fighting...", m->name.c_str()); } ACTION_EPILOUGE; diff --git a/src/world.cpp b/src/world.cpp index bb0487e..4f40a2c 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -8,6 +8,7 @@ #include <algorithm> #include <sstream> #include <fstream> +#include <memory> // local game headers #include <ui.hpp> @@ -342,7 +343,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, @@ -556,17 +557,17 @@ void World::draw(Player *p) pOffset = (offset.x + p->width / 2 - worldStart) / HLINE; // only draw world within player vision - iStart = static_cast<int>(fmax(pOffset - (SCREEN_WIDTH / 2 / HLINE) - GROUND_HILLINESS, 0)); + iStart = std::clamp(static_cast<int>(pOffset - (SCREEN_WIDTH / 2 / HLINE) - GROUND_HILLINESS), + 0, static_cast<int>(lineCount)); iEnd = std::clamp(static_cast<int>(pOffset + (SCREEN_WIDTH / 2 / HLINE)), - static_cast<int>(GROUND_HILLINESS), - static_cast<int>(worldData.size())); + 0, static_cast<int>(lineCount)); // draw the dirt bgTex++; std::vector<std::pair<vec2,vec3>> 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 { @@ -778,15 +779,15 @@ void World::draw(Player *p) std::vector<GLfloat> partVec(pss); GLfloat *pIndex = &partVec[0]; - - for (uint p = 0; p < ps; p++) { + + for (const auto &p : particles) { pc += 30; if (pc > pss) { // TODO resize the vector or something better than breaking - std::cout << "Whoops:" << pc << "," << partVec.size() << std::endl; + //std::cout << "Whoops:" << pc << "," << partVec.size() << std::endl; break; } - particles[p].draw(pIndex); + p.draw(pIndex); } glVertexAttribPointer(worldShader_attribute_coord, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &partVec[0]); @@ -956,6 +957,7 @@ detect(Player *p) 2500 // duration (ms) ); particles.back().fountain = true; + particles.back().stu = b; } break; case FIRE_PIT: @@ -971,6 +973,7 @@ detect(Player *p) ); particles.back().gravity = false; particles.back().behind = true; + particles.back().stu = b; } break; default: @@ -1028,25 +1031,20 @@ update(Player *p, unsigned int delta, unsigned int ticks) } } // iterate through particles - particles.erase(std::remove_if(particles.begin(), particles.end(), [&delta](Particles &part) { - return part.kill(delta); - }), - particles.end()); - - for (auto part = particles.begin(); part != particles.end(); part++) { - auto pa = *part; - - if (pa.canMove) { - (*part).loc.y += pa.vel.y * delta; - (*part).loc.x += pa.vel.x * delta; - - if (std::any_of(std::begin(build), std::end(build), [pa](const Structures *s) { - return (s->bsubtype == FOUNTAIN) && - (pa.loc.x >= s->loc.x) && (pa.loc.x <= s->loc.x + s->width) && - (pa.loc.y <= s->loc.y + s->height * 0.25f); - })) { - particles.erase(part); - } + particles.remove_if([](const Particles &part) { + return part.duration <= 0; + }); + + for (auto &pa : particles) { + if (pa.canMove) { // causes overhead + pa.loc.y += pa.vel.y * delta; + pa.loc.x += pa.vel.x * delta; + + if (pa.stu != nullptr) { + if (pa.loc.x >= pa.stu->loc.x && pa.loc.x <= pa.stu->loc.x + pa.stu->width && + pa.loc.y <= pa.stu->loc.y + pa.stu->height * 0.25f) + pa.duration = 0; + } } } @@ -1130,6 +1128,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()) @@ -1492,13 +1493,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()); } @@ -1518,11 +1515,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()); } @@ -1553,14 +1548,14 @@ addObject(std::string in, std::string p, float x, float y) void World:: addParticle(float x, float y, float w, float h, float vx, float vy, Color color, int d) { - particles.emplace_back(x, y, w, h, vx, vy, color, d); + particles.push_back(Particles(x, y, w, h, vx, vy, color, d)); particles.back().canMove = true; } void World:: addParticle(float x, float y, float w, float h, float vx, float vy, Color color, int d, unsigned char flags) { - particles.emplace_back(x, y, w, h, vx, vy, color, d); + particles.push_back(Particles(x, y, w, h, vx, vy, color, d)); particles.back().canMove = true; particles.back().gravity = flags & (1 << 0); particles.back().bounce = flags & (1 << 1); @@ -1958,37 +1953,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 <World> 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 <IndoorWorld> tag - else if ((wxml = currentXMLDoc.FirstChildElement("IndoorWorld"))) { + else if ((wxml = _currentXMLDoc->FirstChildElement("IndoorWorld"))) { wxml = wxml->FirstChildElement(); vil = NULL; tmp = new IndoorWorld(); @@ -1997,10 +2018,11 @@ XMLDocument currentXMLDoc; // error: can't load a world... else - UserError("XML Error: Cannot find a <World> or <IndoorWorld> tag in " + currentXML + "!"); + UserError("XML Error: Cannot find a <World> or <IndoorWorld> tag in " + _currentXML + "!"); // iterate through world tags while (wxml) { + newEntity = nullptr; name = wxml->Name(); // world linkage @@ -2012,10 +2034,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 @@ -2024,10 +2048,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 @@ -2036,7 +2062,7 @@ XMLDocument currentXMLDoc; // error, invalid link tag else - UserError("XML Error: Invalid <link> tag in " + currentXML + "!"); + UserError("XML Error: Invalid <link> tag in " + _currentXML + "!"); } @@ -2046,9 +2072,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 <style> in " + currentXML + "!"); - tmp->setBackground((WorldBGType)flooor); + unsigned int bgt; + if (wxml->QueryUnsignedAttribute("background", &bgt) != XML_NO_ERROR) + UserError("XML Error: No background given in <style> in " + _currentXML + "!"); + tmp->setBackground(static_cast<WorldBGType>(bgt)); // set BGM file tmp->setBGM(wxml->StrAttribute("bgm")); @@ -2061,112 +2088,99 @@ XMLDocument currentXMLDoc; tmp->generate(wxml->UnsignedAttribute("width")); else { if (Indoor) - UserError("XML Error: <generation> tags can't be in <IndoorWorld> tags (in " + currentXML + ")!"); + UserError("XML Error: <generation> tags can't be in <IndoorWorld> tags (in " + _currentXML + ")!"); else - UserError("XML Error: Invalid <generation> tag in " + currentXML + "!"); + UserError("XML Error: Invalid <generation> tag in " + _currentXML + "!"); } } // mob creation - else if (name == "rabbit") { - tmp->addMob(new Rabbit(), vec2 {0, 0}); - tmp->getLastMob()->createFromXML(wxml); - } else if (name == "bird") { - tmp->addMob(new Bird(), vec2 {0, 0}); - tmp->getLastMob()->createFromXML(wxml); - } else if (name == "trigger") { - tmp->addMob(new Trigger(), vec2 {0, 0}); - tmp->getLastMob()->createFromXML(wxml); - } else if (name == "door") { - tmp->addMob(new Door(), vec2 {0, 0}); - tmp->getLastMob()->createFromXML(wxml); - } else if (name == "page") { - tmp->addMob(new Page(), vec2 {0, 0}); - tmp->getLastMob()->createFromXML(wxml); - } else if (name == "cat") { - tmp->addMob(new Cat(), vec2 {0, 0}); - tmp->getLastMob()->createFromXML(wxml); - } + else if (name == "rabbit") { + newEntity = new Rabbit(); + } else if (name == "bird") { + newEntity = new Bird(); + } else if (name == "trigger") { + newEntity = new Trigger(); + } else if (name == "door") { + newEntity = new Door(); + } else if (name == "page") { + newEntity = new Page(); + } else if (name == "cat") { + newEntity = new Cat(); + } // npc creation else if (name == "npc") { - const char *npcname; - - // spawn at coordinates if desired - if (wxml->QueryFloatAttribute("x", &spawnx) == XML_NO_ERROR) - tmp->addNPC(spawnx, 100); - else - tmp->addNPC(0, 100); - - // name override - if ((npcname = wxml->Attribute("name"))) { - delete[] tmp->npc.back()->name; - tmp->npc.back()->name = new char[strlen(npcname) + 1]; - strcpy(tmp->npc.back()->name, npcname); - } - - // dialog enabling - dialog = false; - if (wxml->QueryBoolAttribute("hasDialog", &dialog) == XML_NO_ERROR && dialog) { - tmp->npc.back()->addAIFunc(false); - } else - tmp->npc.back()->dialogIndex = 9999; - - if (Indoor && wxml->QueryUnsignedAttribute("floor", &flooor) == XML_NO_ERROR) - Indoorp(tmp)->moveToFloor(tmp->npc.back(), flooor); - - // custom health value - if (wxml->QueryFloatAttribute("health", &spawnx) == XML_NO_ERROR) - tmp->npc.back()->health = tmp->npc.back()->maxHealth = spawnx; + newEntity = new NPC(); } // structure creation else if (name == "structure") { - tmp->addStructure((BUILD_SUB) wxml->UnsignedAttribute("type"), - wxml->QueryFloatAttribute("x", &spawnx) != XML_NO_ERROR ? - randGet() % tmp->getTheWidth() / 2.0f : spawnx, - 100, - wxml->StrAttribute("texture"), - wxml->StrAttribute("inside") - ); - } else if (name == "hill") { + newEntity = new Structures(); + } + + // hill creation + else if (name == "hill") { tmp->addHill(ivec2 { wxml->IntAttribute("peakx"), wxml->IntAttribute("peaky") }, wxml->UnsignedAttribute("width")); - } else if (name == "time") { + } + + // time setting + else if (name == "time") { game::time::setTickCount(std::stoi(wxml->GetText())); - } else if (Indoor && name == "floor") { + } + + // floor adding + else if (Indoor && name == "floor") { if (wxml->QueryFloatAttribute("start",&spawnx) == XML_NO_ERROR) Indoorp(tmp)->addFloor(wxml->UnsignedAttribute("width"), spawnx); else Indoorp(tmp)->addFloor(wxml->UnsignedAttribute("width")); } + if (newEntity != nullptr) { + bool alive = true; + if (wxml->QueryBoolAttribute("alive", &alive) != XML_NO_ERROR || alive) { + newEntity->createFromXML(wxml, tmp); + + switch (newEntity->type) { + case NPCT: + tmp->addNPC(dynamic_cast<NPC *>(newEntity)); + break; + case MOBT: + tmp->addMob(dynamic_cast<Mob *>(newEntity), vec2 {0, 0}); + break; + case STRUCTURET: + tmp->addStructure(dynamic_cast<Structures *>(newEntity)); + break; + default: + break; + } + } + } + spawnx = 0; wxml = wxml->NextSiblingElement(); } Village *vptr; + Structures *s; if (vil) { vptr = tmp->addVillage(vil->StrAttribute("name"), tmp); vil = vil->FirstChildElement(); } - std::cout << currentXML << ' ' << tmp->build.size() << '\n'; - while(vil) { name = vil->Name(); - randx = 0; /** * READS DATA ABOUT STRUCTURE CONTAINED IN VILLAGE */ if (name == "structure") { - tmp->addStructure((BUILD_SUB)vil->UnsignedAttribute("type"), - vil->QueryFloatAttribute("x", &spawnx) != XML_NO_ERROR ? randx : spawnx, - 100, - vil->StrAttribute("texture"), - vil->StrAttribute("inside")); + s = new Structures(); + s->createFromXML(vil, tmp); + tmp->addStructure(s); } else if (name == "stall") { sptr = vil->StrAttribute("type"); @@ -2174,23 +2188,17 @@ XMLDocument currentXMLDoc; if (sptr == "market") { // create a structure and a merchant, and pair them - tmp->addStructure(STALL_MARKET, - vil->QueryFloatAttribute("x", &spawnx) != XML_NO_ERROR ? randx : spawnx, - 100, - vil->StrAttribute("texture"), - vil->StrAttribute("inside") - ); + s = new Structures(); + s->createFromXML(vil, tmp); + tmp->addStructure(s); tmp->addMerchant(0, 100, true); } // handle traders else if (sptr == "trader") { - tmp->addStructure(STALL_TRADER, - vil->QueryFloatAttribute("x", &spawnx) != XML_NO_ERROR ? randx : spawnx, - 100, - vil->StrAttribute("texture"), - vil->StrAttribute("inside") - ); + s = new Structures(); + s->createFromXML(vil, tmp); + tmp->addStructure(s); } // loop through buy/sell/trade tags @@ -2246,10 +2254,17 @@ XMLDocument currentXMLDoc; vil = vil->NextSiblingElement(); } - std::ifstream dat (((std::string)currentXML + ".dat").data()); - if (dat.good()) { - dat.close(); - tmp->load(); + if (!loadedLeft && !loadedRight) { + currentXML = _currentXML; + currentXMLRaw = _currentXMLRaw; + + std::ifstream dat ((_currentXML + ".dat").data()); + if (dat.good()) { + dat.close(); + tmp->load(); + } + } else { + delete _currentXMLDoc; } return tmp; diff --git a/win32/main.exe b/win32/main.exe Binary files differindex f77663e..1e00343 100755 --- a/win32/main.exe +++ b/win32/main.exe diff --git a/xml/playerSpawnHill1.xml b/xml/playerSpawnHill1.xml index 2aec9ef..e2479b8 100644 --- a/xml/playerSpawnHill1.xml +++ b/xml/playerSpawnHill1.xml @@ -1,39 +1,33 @@ <?xml version="1.0"?> <World> - <style background="0" bgm="assets/music/embark.wav" folder="assets/style/classic/" /> - <generation type="Random" width="500" /> - <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 /> - - <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" /> - - <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"> - <text> - <greet>Welcome to Smithy's! What would you like to purchase today?</greet> - <accept>Thanks!</accept> - <deny>Come back with more money to get this item!</deny> - <leave>Have a great day, and watch out for my rabbit Mr. Cuddles, he might try to attack you.</leave> - </text> - <trade quantity="420" item="Dank MayMay" quantity1="1" item1="Wood Sword"/> - <trade quantity="666" item="Wood Sword" quantity1="420" item1="Dank MayMay"/> - </stall> - </village> + <style background="0" bgm="assets/music/embark.wav" folder="assets/style/classic/"/> + <generation type="Random" width="500"/> + <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/> + <!--<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"/> + <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"> + <text> + <greet>Welcome to Smithy's! What would you like to purchase today?</greet> + <accept>Thanks!</accept> + <deny>Come back with more money to get this item!</deny> + <leave>Have a great day, and watch out for my rabbit Mr. Cuddles, he might try to attack you.</leave> + </text> + <trade quantity="420" item="Dank MayMay" quantity1="1" item1="Wood Sword"/> + <trade quantity="666" item="Wood Sword" quantity1="420" item1="Dank MayMay"/> + </stall> + </village> </World> <Trigger id="Test">It was a dark and stormy night... @@ -42,45 +36,37 @@ And it wasn't stormy. ...</Trigger> <Dialog name="Ralph"> - - <text id="0" nextid="1"> + <text id="0" nextid="1"> Hello there! My name is Ralph. <gotox>300</gotox> - </text> - - <text id="1" nextid="2" call="Johnny" callid="0" pause="true" > + </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" > + <text id="2"> Niice. - <quest check="Your First Quest" fail="3" /> - </text> - - <text id="3"> + <quest check="Your First Quest" fail="3"/></text> + <text id="3"> Go check out Johnny. He's cool. </text> </Dialog> <Dialog name="Johnny"> - <text id="0" nextid="1" pause="true" > + <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" > - Dank MayMay,2 - Wood Sword,1 + <quest assign="Your First Quest"> + Dank MayMay,2 + Wood Sword,1 </quest> - </text> - - <text id="1" nextid="1" pause="true" > + </text> + <text id="1" nextid="1" pause="true"> Broooooooooooooo... </text> </Dialog> <Dialog name="Big Dave"> - <text id="0" pause="true"> + <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"/> |