aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog17
-rw-r--r--Makefile2
-rw-r--r--assets/blankNormal.pngbin0 -> 172 bytes
-rw-r--r--assets/cat_normal.pngbin0 -> 820 bytes
-rw-r--r--assets/cat_normal_old.pngbin0 -> 684 bytes
-rw-r--r--assets/dialog_en-us15
-rw-r--r--assets/items/basic_torch.pngbin0 -> 317 bytes
-rw-r--r--assets/style/classic/bg/bgnew.pngbin0 -> 821843 bytes
-rw-r--r--assets/style/classic/bg/star.pngbin0 -> 731 bytes
-rw-r--r--include/common.hpp2
-rw-r--r--include/coolarray.hpp113
-rw-r--r--include/entities.hpp145
-rw-r--r--include/mob.hpp14
-rw-r--r--include/world.hpp23
-rw-r--r--main.cpp102
-rw-r--r--src/common.cpp33
-rw-r--r--src/entities.cpp146
-rw-r--r--src/mob.cpp25
-rw-r--r--src/ui.cpp6
-rw-r--r--src/ui_action.cpp2
-rw-r--r--src/world.cpp303
-rwxr-xr-xwin32/main.exebin6027539 -> 6226815 bytes
-rw-r--r--xml/playerSpawnHill1.xml96
23 files changed, 655 insertions, 389 deletions
diff --git a/Changelog b/Changelog
index c81def9..ec4a00e 100644
--- a/Changelog
+++ b/Changelog
@@ -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???
diff --git a/Makefile b/Makefile
index 7c05c95..31899a5 100644
--- a/Makefile
+++ b/Makefile
@@ -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
new file mode 100644
index 0000000..cff3ee7
--- /dev/null
+++ b/assets/blankNormal.png
Binary files differ
diff --git a/assets/cat_normal.png b/assets/cat_normal.png
new file mode 100644
index 0000000..59aaee8
--- /dev/null
+++ b/assets/cat_normal.png
Binary files differ
diff --git a/assets/cat_normal_old.png b/assets/cat_normal_old.png
new file mode 100644
index 0000000..c3ed4aa
--- /dev/null
+++ b/assets/cat_normal_old.png
Binary files differ
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
new file mode 100644
index 0000000..fe6a994
--- /dev/null
+++ b/assets/items/basic_torch.png
Binary files differ
diff --git a/assets/style/classic/bg/bgnew.png b/assets/style/classic/bg/bgnew.png
new file mode 100644
index 0000000..05c352b
--- /dev/null
+++ b/assets/style/classic/bg/bgnew.png
Binary files differ
diff --git a/assets/style/classic/bg/star.png b/assets/style/classic/bg/star.png
new file mode 100644
index 0000000..6360d30
--- /dev/null
+++ b/assets/style/classic/bg/star.png
Binary files differ
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;
diff --git a/main.cpp b/main.cpp
index 8c41258..4f4b519 100644
--- a/main.cpp
+++ b/main.cpp
@@ -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;
diff --git a/src/ui.cpp b/src/ui.cpp
index 1f6e593..f32bc79 100644
--- a/src/ui.cpp
+++ b/src/ui.cpp
@@ -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 = &currentXMLDoc;
+ 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
index f77663e..1e00343 100755
--- a/win32/main.exe
+++ b/win32/main.exe
Binary files differ
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&apos;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"/>