+++ /dev/null
-/* ----------------------------------------------------------------------------
-** The entity stuffs.
-**
-** Entities.
-** --------------------------------------------------------------------------*/
-#ifndef ENTITIES_H
-#define ENTITIES_H
-#define DEBUG
-
-/* ----------------------------------------------------------------------------
-** Includes section
-** --------------------------------------------------------------------------*/
-
-// local game includes
-#include <common.hpp>
-#include <quest.hpp>
-#include <inventory.hpp>
-#include <texture.hpp>
-#include <save_util.hpp>
-#include <coolarray.hpp>
-
-// local library includes
-#include <tinyxml2.h>
-using namespace tinyxml2;
-
-/* ----------------------------------------------------------------------------
-** Structures section
-** --------------------------------------------------------------------------*/
-
-/**
- * An entity type enumerator for identifying entities.
- */
-enum _TYPE {
- UNKNOWNT = -999, /**< who knows? */
- OBJECTT = -2, /**< an object (Object) */
- STRUCTURET, /**< a structure (Structures *) */
- PLAYERT, /**< the player (Player *) */
- NPCT, /**< an NPC (NPC *) */
- MERCHT, /**< a merchant (Merchant *) */
- MOBT /**< A mob (Mob *) */
-};
-
-/**
- * An enumerator for entity gender.
- */
-enum GENDER{
- MALE, /**< male */
- FEMALE /**< female */
-};
-
-/**
- * An enumerator for strcture types.
- * The subtype of a structure will affect how it is drawn and how it functions.
- */
-enum BUILD_SUB{
- TOWN_HALL = 0, /**< a town hall */
- HOUSE, /**< a generic house */
- HOUSE2, /**< a generic house of a different style */
- HOUSE3, /**< a generic house of a different style */
- HOUSE4, /**< a generic house of a different style */
- FOUNTAIN, /**< a fountain, creates water particles */
- LAMP_POST, /**< a lamppost, creates light */
- FIRE_PIT, /**< a firepit, creates fire particles / light */
- STALL_MARKET = 70, /**< a stall for a merchant */
- STALL_TRADER
-};
-
-/**
- * A structure for tracking potential trades between the player and a merchant.
- */
-struct Trade {
- // the names of the items up for trade
- std::string item[2];
- // how much of each item to trade
- int quantity[2];
-
- // constructs a trade with the given values
- Trade(int qo, std::string o, int qt, std::string t) {
- item[0] = o;
- item[1] = t;
- quantity[0] = qo;
- quantity[1] = qt;
- }
-
- // creates an empty trade item
- Trade(void) {
- item[0] = "";
- item[1] = "";
- quantity[0] = 0;
- quantity[1] = 0;
- }
-};
-typedef struct Trade Trade;
-
-/* ----------------------------------------------------------------------------
-** Variables section
-** --------------------------------------------------------------------------*/
-
-// the size of the player's inventory
-extern const unsigned int PLAYER_INV_SIZE;
-// the size of an NPC's inventory
-extern const unsigned int NPC_INV_SIZE;
-
-/* ----------------------------------------------------------------------------
-** Classes / function prototypes section
-** --------------------------------------------------------------------------*/
-
-// a prototype of the world class, necessary for some function prototypes
-class World;
-class IndoorWorld;
-
-/**
- * The light structure, used to store light coordinates and color.
- */
-
-class Light{
-public:
- vec2 loc; /**< Light location */
- Color color; /**< Light color */
- float radius; /**< Light radius */
-
- bool belongsTo;
- Entity *following;
-
- bool flame;
- float fireFlicker;
- vec2 fireLoc;
- Light()
- {
- loc = vec2(0,0);
- color = Color(1.0, 1.0, 1.0);
- radius = 0;
-
- belongsTo = false;
- following = nullptr;
-
- flame = false;
- }
-
- Light(vec2 l, float r, Color c)
- {
- loc = l;
- color = c;
- radius = r;
-
- belongsTo = false;
- following = nullptr;
-
- flame = false;
- }
-
- void follow(Entity *f)
- {
- following = f;
- belongsTo = true;
- }
-
- void makeFlame(void)
- {
- flame = true;
- }
-
- void createFromXML(XMLElement *e);
-};
-
-/**
- * The entity class.
- * This class contains common functions and variables for all types of
- * entities, i.e. a common structure.
- */
-class Entity{
-protected:
- // an incrementer for invincibility after a hit
- unsigned int hitCooldown;
-
- // an incrementer for triggering change of movement with wander()
- int ticksToUse;
-
- // entity handles an applied hit (sword) if set true
- bool forcedMove;
-
- // if set false, entity will be destroyed
- bool alive;
-
- // TODO
- float targetx;
-
- // the cooldown display (red overlay)
- float hitDuration;
-
- // 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;
- float z;
-
- // contains the entity's velocity, in pixels
- vec2 vel;
-
- // the entity's width, in pixels
- float width;
-
- // the entity's height, in pixels
- float height;
-
- // a speed multiplier, applied to velocity
- float speed;
-
- // when true player may interact, and the entity's name will be drawn
- bool near;
-
- // when true, the entity can move
- int canMove;
-
- // tells direction entity is facing
- bool right, left;
-
- // tells if the entity is from another world
- char outnabout;
-
- // set to 1 if entity is on the ground, 0 if in the air
- unsigned char ground;
-
- // the entity's inventory
- Inventory *inv;
-
- // the entity's light
- Light light;
-
- // the entity's health
- float health;
-
- // the most health the entity can have
- float maxHealth;
-
- // the type of the entity
- _TYPE type;
-
- // the entity's subtype, if applicable
- int subtype;
-
- // the entity's name, randomly generated on spawn
- std::string name;
-
- // the entity's gender
- GENDER gender;
-
- // a texture handler for the entity
- TextureIterator tex;
-
- // draws the entity to the screen
- void draw(void);
-
- // spawns the entity at the given coordinates
- void spawn(float, float);
-
- // allows the entity to wander, according to what class is deriving this.
- virtual void wander(int){}
- virtual void wander(void){}
-
- // allows the entity to interact with the player
- virtual void interact(void){}
-
- // causes the entity to move to the given x coordinate
- void moveTo(float dest_x);
-
- // causes the entity to follow the one provided
- void follow(Entity *e);
-
- // causes the entity to take a player-inflicted hit
- void takeHit(unsigned int _health, unsigned int cooldown);
-
- // returns the amount of cool down before next hit
- unsigned int coolDown();
-
- // set the cool down
- void setCooldown(unsigned int c);
-
- // handles hits if they've been taken
- void handleHits(void);
-
- // insures that the entity is dead
- void die(void);
-
- // checks if the entity is alive
- bool isAlive(void) const;
-
- // checks if the entity is hit in some way
- bool isHit(void) const;
-
- // returns true if this entity is near the one provided
- bool isNear(const Entity *e);
-
- // 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;
- virtual void saveToXML(void) =0;
-
-/* Entity
-
- **
- * Forces the given entity to follow this one.
- *
- void lead(Entity *e, unsigned int how);
-
- **
- * Attempts to break free from any following.
- *
- void unfollow(void);*/
-
- // a common constructor, clears variables
- Entity(void);
-
- // frees memory taken by the entity
- virtual ~Entity(){}
-};
-
-class Player : public Entity {
-public:
- Entity *ride;
- QuestHandler qh;
-
- Player();
- ~Player();
- void save(void);
- void sspawn(float x,float y);
- void createFromXML(XMLElement *e, World *w);
- void saveToXML(void);
-};
-
-class Structures : public Entity {
-public:
- BUILD_SUB bsubtype;
- World *inWorld;
- World *insideWorld;
- std::string inside;
- std::string textureLoc;
-
- GLuint insideTex;
-
- Structures();
- ~Structures();
-
- unsigned int spawn(BUILD_SUB, float, float);
- void createFromXML(XMLElement *e, World *w);
- void saveToXML(void);
-};
-
-
-class NPC : public Entity {
-private:
- // the number of the random dialog to use
- unsigned int randDialog;
-
- unsigned int dialogCount;
-
-public:
- int dialogIndex;
-
- NPC();
- ~NPC();
-
- void drawThingy(void) const;
-
- void addAIFunc(bool preload);
-
- void interact();
- void wander(int);
- void createFromXML(XMLElement *e, World *w);
- void saveToXML(void);
-};
-
-class Merchant : public NPC {
-public:
- std::vector<Trade>trade;
- uint currTrade;
-
- std::string text[4];
- std::string *toSay;
- //greeting
- //accept
- //deny
- //farewell
-
- void interact();
- Structures *inside;
-
- Merchant();
- ~Merchant();
-
- void wander(int);
- void saveToXML(void);
-};
-
-class Object : public Entity{
-public:
- std::string iname;
- std::string pickupDialog;
- bool questObject = false;
-
- Object();
- Object(std::string in,std::string pd);
- ~Object();
-
- void reloadTexture(void);
-
- void interact(void);
-
- bool operator==(const Object &o) {
- return (name == o.name) && (loc == o.loc);
- }
- void createFromXML(XMLElement *e, World *w);
- void saveToXML(void);
-};
-
-/**
- * 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>
-
-constexpr Object *Objectp(Entity *e) {
- return (Object *)e;
-}
-
-constexpr NPC *NPCp(Entity *e) {
- return (NPC *)e;
-}
-
-constexpr Structures *Structurep(Entity *e) {
- return (Structures *)e;
-}
-
-constexpr Merchant *Merchantp(Entity *e) {
- return (Merchant *)e;
-}
-
-#include <entityx/entityx.h>
-#include <events.hpp>
-
-class PlayerSystem : public entityx::System<PlayerSystem>, public entityx::Receiver<PlayerSystem> {
-private:
- Player **m_Player;
- bool m_MoveLeft, m_MoveRight;
-
-public:
- PlayerSystem(Player **p)
- : m_Player(p), m_MoveLeft(false), m_MoveRight(false) {}
-
- void update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) override;
-
- void configure(entityx::EventManager &ev);
- void receive(const KeyDownEvent &kde);
- void receive(const KeyUpEvent &kue);
-};
-
-
-#endif // ENTITIES_H
-
-/**
-ENTITY TYPES
--1 STRUCTURES
-|->1 Village
-|->2 Castle
-|
-0 PLAYERS
-|->Player
-|
-1 NPCS
-|->0 Base
-|->1 Merchant
-|
-2 MOBS
-|->1 Rabbit
-|->2 Bird
-**/
--- /dev/null
+/* ----------------------------------------------------------------------------
+** The entity stuffs.
+**
+** Entities.
+** --------------------------------------------------------------------------*/
+#ifndef ENTITIES_H
+#define ENTITIES_H
+#define DEBUG
+
+/* ----------------------------------------------------------------------------
+** Includes section
+** --------------------------------------------------------------------------*/
+
+// local game includes
+#include <common.hpp>
+#include <quest.hpp>
+#include <inventory.hpp>
+#include <texture.hpp>
+#include <save_util.hpp>
+#include <coolarray.hpp>
+
+// local library includes
+#include <tinyxml2.h>
+using namespace tinyxml2;
+
+/* ----------------------------------------------------------------------------
+** Structures section
+** --------------------------------------------------------------------------*/
+
+/**
+ * An entity type enumerator for identifying entities.
+ */
+enum _TYPE {
+ UNKNOWNT = -999, /**< who knows? */
+ OBJECTT = -2, /**< an object (Object) */
+ STRUCTURET, /**< a structure (Structures *) */
+ PLAYERT, /**< the player (Player *) */
+ NPCT, /**< an NPC (NPC *) */
+ MERCHT, /**< a merchant (Merchant *) */
+ MOBT /**< A mob (Mob *) */
+};
+
+/**
+ * An enumerator for entity gender.
+ */
+enum GENDER{
+ MALE, /**< male */
+ FEMALE /**< female */
+};
+
+/**
+ * An enumerator for strcture types.
+ * The subtype of a structure will affect how it is drawn and how it functions.
+ */
+enum BUILD_SUB{
+ TOWN_HALL = 0, /**< a town hall */
+ HOUSE, /**< a generic house */
+ HOUSE2, /**< a generic house of a different style */
+ HOUSE3, /**< a generic house of a different style */
+ HOUSE4, /**< a generic house of a different style */
+ FOUNTAIN, /**< a fountain, creates water particles */
+ LAMP_POST, /**< a lamppost, creates light */
+ FIRE_PIT, /**< a firepit, creates fire particles / light */
+ STALL_MARKET = 70, /**< a stall for a merchant */
+ STALL_TRADER
+};
+
+/**
+ * A structure for tracking potential trades between the player and a merchant.
+ */
+struct Trade {
+ // the names of the items up for trade
+ std::string item[2];
+ // how much of each item to trade
+ int quantity[2];
+
+ // constructs a trade with the given values
+ Trade(int qo, std::string o, int qt, std::string t) {
+ item[0] = o;
+ item[1] = t;
+ quantity[0] = qo;
+ quantity[1] = qt;
+ }
+
+ // creates an empty trade item
+ Trade(void) {
+ item[0] = "";
+ item[1] = "";
+ quantity[0] = 0;
+ quantity[1] = 0;
+ }
+};
+typedef struct Trade Trade;
+
+/* ----------------------------------------------------------------------------
+** Variables section
+** --------------------------------------------------------------------------*/
+
+// the size of the player's inventory
+extern const unsigned int PLAYER_INV_SIZE;
+// the size of an NPC's inventory
+extern const unsigned int NPC_INV_SIZE;
+
+/* ----------------------------------------------------------------------------
+** Classes / function prototypes section
+** --------------------------------------------------------------------------*/
+
+// a prototype of the world class, necessary for some function prototypes
+class World;
+class IndoorWorld;
+
+/**
+ * The light structure, used to store light coordinates and color.
+ */
+
+class Light{
+public:
+ vec2 loc; /**< Light location */
+ Color color; /**< Light color */
+ float radius; /**< Light radius */
+
+ bool belongsTo;
+ Entity *following;
+
+ bool flame;
+ float fireFlicker;
+ vec2 fireLoc;
+ Light()
+ {
+ loc = vec2(0,0);
+ color = Color(1.0, 1.0, 1.0);
+ radius = 0;
+
+ belongsTo = false;
+ following = nullptr;
+
+ flame = false;
+ }
+
+ Light(vec2 l, float r, Color c)
+ {
+ loc = l;
+ color = c;
+ radius = r;
+
+ belongsTo = false;
+ following = nullptr;
+
+ flame = false;
+ }
+
+ void follow(Entity *f)
+ {
+ following = f;
+ belongsTo = true;
+ }
+
+ void makeFlame(void)
+ {
+ flame = true;
+ }
+
+ void createFromXML(XMLElement *e);
+};
+
+/**
+ * The entity class.
+ * This class contains common functions and variables for all types of
+ * entities, i.e. a common structure.
+ */
+class Entity{
+protected:
+ // an incrementer for invincibility after a hit
+ unsigned int hitCooldown;
+
+ // an incrementer for triggering change of movement with wander()
+ int ticksToUse;
+
+ // entity handles an applied hit (sword) if set true
+ bool forcedMove;
+
+ // if set false, entity will be destroyed
+ bool alive;
+
+ // TODO
+ float targetx;
+
+ // the cooldown display (red overlay)
+ float hitDuration;
+
+ // 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;
+ float z;
+
+ // contains the entity's velocity, in pixels
+ vec2 vel;
+
+ // the entity's width, in pixels
+ float width;
+
+ // the entity's height, in pixels
+ float height;
+
+ // a speed multiplier, applied to velocity
+ float speed;
+
+ // when true player may interact, and the entity's name will be drawn
+ bool near;
+
+ // when true, the entity can move
+ int canMove;
+
+ // tells direction entity is facing
+ bool right, left;
+
+ // tells if the entity is from another world
+ char outnabout;
+
+ // set to 1 if entity is on the ground, 0 if in the air
+ unsigned char ground;
+
+ // the entity's inventory
+ Inventory *inv;
+
+ // the entity's light
+ Light light;
+
+ // the entity's health
+ float health;
+
+ // the most health the entity can have
+ float maxHealth;
+
+ // the type of the entity
+ _TYPE type;
+
+ // the entity's subtype, if applicable
+ int subtype;
+
+ // the entity's name, randomly generated on spawn
+ std::string name;
+
+ // the entity's gender
+ GENDER gender;
+
+ // a texture handler for the entity
+ TextureIterator tex;
+
+ // draws the entity to the screen
+ void draw(void);
+
+ // spawns the entity at the given coordinates
+ void spawn(float, float);
+
+ // allows the entity to wander, according to what class is deriving this.
+ virtual void wander(int){}
+ virtual void wander(void){}
+
+ // allows the entity to interact with the player
+ virtual void interact(void){}
+
+ // causes the entity to move to the given x coordinate
+ void moveTo(float dest_x);
+
+ // causes the entity to follow the one provided
+ void follow(Entity *e);
+
+ // causes the entity to take a player-inflicted hit
+ void takeHit(unsigned int _health, unsigned int cooldown);
+
+ // returns the amount of cool down before next hit
+ unsigned int coolDown();
+
+ // set the cool down
+ void setCooldown(unsigned int c);
+
+ // handles hits if they've been taken
+ void handleHits(void);
+
+ // insures that the entity is dead
+ void die(void);
+
+ // checks if the entity is alive
+ bool isAlive(void) const;
+
+ // checks if the entity is hit in some way
+ bool isHit(void) const;
+
+ // returns true if this entity is near the one provided
+ bool isNear(const Entity *e);
+
+ // 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;
+ virtual void saveToXML(void) =0;
+
+/* Entity
+
+ **
+ * Forces the given entity to follow this one.
+ *
+ void lead(Entity *e, unsigned int how);
+
+ **
+ * Attempts to break free from any following.
+ *
+ void unfollow(void);*/
+
+ // a common constructor, clears variables
+ Entity(void);
+
+ // frees memory taken by the entity
+ virtual ~Entity(){}
+};
+
+class Player : public Entity {
+public:
+ Entity *ride;
+ QuestHandler qh;
+
+ Player();
+ ~Player();
+ void save(void);
+ void sspawn(float x,float y);
+ void createFromXML(XMLElement *e, World *w);
+ void saveToXML(void);
+};
+
+class Structures : public Entity {
+public:
+ BUILD_SUB bsubtype;
+ World *inWorld;
+ World *insideWorld;
+ std::string inside;
+ std::string textureLoc;
+
+ GLuint insideTex;
+
+ Structures();
+ ~Structures();
+
+ unsigned int spawn(BUILD_SUB, float, float);
+ void createFromXML(XMLElement *e, World *w);
+ void saveToXML(void);
+};
+
+
+class NPC : public Entity {
+private:
+ // the number of the random dialog to use
+ unsigned int randDialog;
+
+ unsigned int dialogCount;
+
+public:
+ int dialogIndex;
+
+ NPC();
+ ~NPC();
+
+ void drawThingy(void) const;
+
+ void addAIFunc(bool preload);
+
+ void interact();
+ void wander(int);
+ void createFromXML(XMLElement *e, World *w);
+ void saveToXML(void);
+};
+
+class Merchant : public NPC {
+public:
+ std::vector<Trade>trade;
+ uint currTrade;
+
+ std::string text[4];
+ std::string *toSay;
+ //greeting
+ //accept
+ //deny
+ //farewell
+
+ void interact();
+ Structures *inside;
+
+ Merchant();
+ ~Merchant();
+
+ void wander(int);
+ void saveToXML(void);
+};
+
+class Object : public Entity{
+public:
+ std::string iname;
+ std::string pickupDialog;
+ bool questObject = false;
+
+ Object();
+ Object(std::string in,std::string pd);
+ ~Object();
+
+ void reloadTexture(void);
+
+ void interact(void);
+
+ bool operator==(const Object &o) {
+ return (name == o.name) && (loc == o.loc);
+ }
+ void createFromXML(XMLElement *e, World *w);
+ void saveToXML(void);
+};
+
+/**
+ * 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>
+
+constexpr Object *Objectp(Entity *e) {
+ return (Object *)e;
+}
+
+constexpr NPC *NPCp(Entity *e) {
+ return (NPC *)e;
+}
+
+constexpr Structures *Structurep(Entity *e) {
+ return (Structures *)e;
+}
+
+constexpr Merchant *Merchantp(Entity *e) {
+ return (Merchant *)e;
+}
+
+#include <entityx/entityx.h>
+#include <events.hpp>
+
+class PlayerSystem : public entityx::System<PlayerSystem>, public entityx::Receiver<PlayerSystem> {
+private:
+ Player **m_Player;
+ bool m_MoveLeft, m_MoveRight;
+
+public:
+ PlayerSystem(Player **p)
+ : m_Player(p), m_MoveLeft(false), m_MoveRight(false) {}
+
+ void update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) override;
+
+ void configure(entityx::EventManager &ev);
+ void receive(const KeyDownEvent &kde);
+ void receive(const KeyUpEvent &kue);
+};
+
+
+#endif // ENTITIES_H
+
+/**
+ENTITY TYPES
+-1 STRUCTURES
+|->1 Village
+|->2 Castle
+|
+0 PLAYERS
+|->Player
+|
+1 NPCS
+|->0 Base
+|->1 Merchant
+|
+2 MOBS
+|->1 Rabbit
+|->2 Bird
+**/
+++ /dev/null
-#ifndef INVENTORY_H
-#define INVENTORY_H
-
-#include <common.hpp>
-#include <string.h>
-
-#include <texture.hpp>
-#include <events.hpp>
-
-#define DEBUG
-
-class Entity;
-
-/**
- * The base item class
- * This stores the name, width, height, and texture(s)
- */
-class Item {
-private:
- bool beingUsed;
-
-protected:
- std::vector<Entity*> interact;
-
-public:
-
- // what we want to call each item
- std::string name;
-
- // how many pixel tall and white each thing is
- dim2 dim;
-
- // the total amount of this item each slot can have
- uint maxStackSize;
-
- // the array of textures for each frame of animation
- Texturec *tex;
-
- // how much the item is rotated in the hand
- float rotation = 0.0f;
-
- // return if the item is currently in use
- virtual bool inUse();
-
- // set the state of the item
- virtual void setUse(bool use);
-
- // add entities to the list of those being interacted
- virtual void addInteract(Entity* e);
- virtual void addInteract(std::vector<Entity*> e);
-
- /**
- * The function we use to call the child classes ability
- * Note: Since this function is abstract, we HAVE to create one for each
- * child class/type of item.
- */
- virtual int useItem()=0;
-
- virtual Item* clone()=0;
-
- // destructor
- virtual ~Item();
- // return the first texture for the item
- GLuint rtex();
-
- // return the nth texture for the item
- GLuint rtex(int n);
-};
-
-/**
- * Class for blank items, we use this for items that do not have an ability
- * Like Quest or Debug items
- */
-class BaseItem : public Item {
-public:
- // since the items don't have a use, we don't make one for it
- int useItem();
-
- BaseItem* clone();
-
- //~BaseItem(){}
-};
-
-/**
- * Sword class. This is for swords, y'know. Pretty basic stuff
- */
-class Sword : public Item {
-// can't touch this
-private:
- /**
- * How much damage our sword will do
- * notice that it's private to avoid a change
- */
- float damage;
-
- Ray hitbox;
-
-//can touch this
-public:
- /**
- * Lets us return the amount of damage the sword has
- * TODO takes into account enchants and/or buffs/nerfs
- */
- //TODO move
- float getDamage();
-
- // set the damage of the sword
- void setDamage(float d);
-
- /**
- * handles the swinging of the sword
- */
- //TODO move
- int useItem();
-
- Sword* clone();
-};
-
-class Arrow : public Item {
-private:
- // same as sword
- float damage;
-public:
-
- // see sword
- float getDamage();
-
- // sets amount of damage
- void setDamage(float d);
-
- // uses item
- int useItem();
-
- Arrow *clone();
-};
-
-/**
- * Bow class. We use this for shooting bow and arrows
- */
-class Bow : public Item {
-private:
- // same as sword
- float damage;
-public:
- // returns the amount of damage, see sword
- float getDamage();
-
- // sets the amount of damages
- void setDamage(float d);
-
- // handles shooting and arrow curving
- int useItem();
-
- Bow* clone();
-};
-
-/**
- * Raw food class, this will be used for uncooked meats...
- * TODO Eating this may cause health loss, salmonela, mad cow diese
- */
-class RawFood : public Item {
-private:
- // the amount of the health the food heals
- float health;
-
-public:
- // since the health is private, we get how much it is here
- float getHealth();
-
- // TODO chance to hurt
- virtual int useItem();
-
- RawFood* clone();
-};
-
-/**
- * Cooked/Naturale food class
- * When this food is consumed, higher stats are gained than Raw Food and
- * there is no chance of damage/de-buffs
- */
-class Food : public RawFood {
-private:
-public:
-
- // consume food in hand, no chance for de-buff;
- int useItem();
-
- Food* clone();
-};
-
-class ItemLight : public Item {
-private:
- // the color of the light
- Color color;
-public:
- // turn on/off the light
- // TODO
- int useItem();
-
- ItemLight* clone();
-};
-
-/**
- * Currency class. Well, it's used for currency
- */
-class NewCurrency : public Item {
-private:
- // how much the coin is "worth" so to say
- int value;
-public:
- // get the value of the coin
- int getValue();
-
- // TODO maybe play a jingling noise
- // probably won't have a use
- int useItem();
-
- NewCurrency(){}
- ~NewCurrency(){}
-};
-
-/***********************************************************************************
- * OLD STUFF THAT NEEDS TO GET UPDATED *
- **********************************************************************************/
-
-using InventorySlot = std::pair<Item *, unsigned int>;
-
-class Inventory {
-private:
- unsigned int size; //how many slots our inventory has
- unsigned int sel; //what item is currently selected
- int os = 0;
-public:
- std::vector<InventorySlot> Items;
-
- bool invOpen = false; //is the inventory open
- bool invOpening = false; //is the opening animation playing
- bool invHover = false; //are we using the fancy hover inventory
- bool selected = false; //used in hover inventory to show which item has been selected
- bool mouseSel = false; //the location of the temperary selection for the hover inv
- bool usingi = false; //bool used to tell if inventory owner is using selected item
-
- Inventory(unsigned int s); // Creates an inventory of size 's'
- ~Inventory(void); // Free's allocated memory
-
- int useCurrent();
- void currentAddInteract(Entity* e);
- void currentAddInteract(std::vector<Entity*> e);
-
- int addItem(std::string name,uint count);
- int takeItem(std::string name,uint count);
- int hasItem(std::string name);
-
- int useItem(void);
- bool detectCollision(vec2,vec2);
-
- void setSelection(unsigned int s);
- void setSelectionUp();
- void setSelectionDown();
-
- void draw(void); // Draws a text list of items in this inventory (should only be called for the player for now)
-
- const Item* getCurrentItem(void);
-};
-
-void initInventorySprites(void);
-void destroyInventory(void);
-
-const char *getItemTexturePath(std::string name);
-GLuint getItemTexture(std::string name);
-float getItemWidth(std::string name);
-float getItemHeight(std::string name);
-
-#include <entityx/entityx.h>
-
-class InventorySystem : public entityx::System<InventorySystem>, public entityx::Receiver<InventorySystem> {
-public:
- void update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) override;
-
- void configure(entityx::EventManager &em);
- void receive(const MouseScrollEvent &mse);
-};
-
-#endif // INVENTORY_H
--- /dev/null
+#ifndef INVENTORY_H
+#define INVENTORY_H
+
+#include <common.hpp>
+#include <string.h>
+
+#include <texture.hpp>
+#include <events.hpp>
+
+#define DEBUG
+
+class Entity;
+
+/**
+ * The base item class
+ * This stores the name, width, height, and texture(s)
+ */
+class Item {
+private:
+ bool beingUsed;
+
+protected:
+ std::vector<Entity*> interact;
+
+public:
+
+ // what we want to call each item
+ std::string name;
+
+ // how many pixel tall and white each thing is
+ dim2 dim;
+
+ // the total amount of this item each slot can have
+ uint maxStackSize;
+
+ // the array of textures for each frame of animation
+ Texturec *tex;
+
+ // how much the item is rotated in the hand
+ float rotation = 0.0f;
+
+ // return if the item is currently in use
+ virtual bool inUse();
+
+ // set the state of the item
+ virtual void setUse(bool use);
+
+ // add entities to the list of those being interacted
+ virtual void addInteract(Entity* e);
+ virtual void addInteract(std::vector<Entity*> e);
+
+ /**
+ * The function we use to call the child classes ability
+ * Note: Since this function is abstract, we HAVE to create one for each
+ * child class/type of item.
+ */
+ virtual int useItem()=0;
+
+ virtual Item* clone()=0;
+
+ // destructor
+ virtual ~Item();
+ // return the first texture for the item
+ GLuint rtex();
+
+ // return the nth texture for the item
+ GLuint rtex(int n);
+};
+
+/**
+ * Class for blank items, we use this for items that do not have an ability
+ * Like Quest or Debug items
+ */
+class BaseItem : public Item {
+public:
+ // since the items don't have a use, we don't make one for it
+ int useItem();
+
+ BaseItem* clone();
+
+ //~BaseItem(){}
+};
+
+/**
+ * Sword class. This is for swords, y'know. Pretty basic stuff
+ */
+class Sword : public Item {
+// can't touch this
+private:
+ /**
+ * How much damage our sword will do
+ * notice that it's private to avoid a change
+ */
+ float damage;
+
+ Ray hitbox;
+
+//can touch this
+public:
+ /**
+ * Lets us return the amount of damage the sword has
+ * TODO takes into account enchants and/or buffs/nerfs
+ */
+ //TODO move
+ float getDamage();
+
+ // set the damage of the sword
+ void setDamage(float d);
+
+ /**
+ * handles the swinging of the sword
+ */
+ //TODO move
+ int useItem();
+
+ Sword* clone();
+};
+
+class Arrow : public Item {
+private:
+ // same as sword
+ float damage;
+public:
+
+ // see sword
+ float getDamage();
+
+ // sets amount of damage
+ void setDamage(float d);
+
+ // uses item
+ int useItem();
+
+ Arrow *clone();
+};
+
+/**
+ * Bow class. We use this for shooting bow and arrows
+ */
+class Bow : public Item {
+private:
+ // same as sword
+ float damage;
+public:
+ // returns the amount of damage, see sword
+ float getDamage();
+
+ // sets the amount of damages
+ void setDamage(float d);
+
+ // handles shooting and arrow curving
+ int useItem();
+
+ Bow* clone();
+};
+
+/**
+ * Raw food class, this will be used for uncooked meats...
+ * TODO Eating this may cause health loss, salmonela, mad cow diese
+ */
+class RawFood : public Item {
+private:
+ // the amount of the health the food heals
+ float health;
+
+public:
+ // since the health is private, we get how much it is here
+ float getHealth();
+
+ // TODO chance to hurt
+ virtual int useItem();
+
+ RawFood* clone();
+};
+
+/**
+ * Cooked/Naturale food class
+ * When this food is consumed, higher stats are gained than Raw Food and
+ * there is no chance of damage/de-buffs
+ */
+class Food : public RawFood {
+private:
+public:
+
+ // consume food in hand, no chance for de-buff;
+ int useItem();
+
+ Food* clone();
+};
+
+class ItemLight : public Item {
+private:
+ // the color of the light
+ Color color;
+public:
+ // turn on/off the light
+ // TODO
+ int useItem();
+
+ ItemLight* clone();
+};
+
+/**
+ * Currency class. Well, it's used for currency
+ */
+class NewCurrency : public Item {
+private:
+ // how much the coin is "worth" so to say
+ int value;
+public:
+ // get the value of the coin
+ int getValue();
+
+ // TODO maybe play a jingling noise
+ // probably won't have a use
+ int useItem();
+
+ NewCurrency(){}
+ ~NewCurrency(){}
+};
+
+/***********************************************************************************
+ * OLD STUFF THAT NEEDS TO GET UPDATED *
+ **********************************************************************************/
+
+using InventorySlot = std::pair<Item *, unsigned int>;
+
+class Inventory {
+private:
+ unsigned int size; //how many slots our inventory has
+ unsigned int sel; //what item is currently selected
+ int os = 0;
+public:
+ std::vector<InventorySlot> Items;
+
+ bool invOpen = false; //is the inventory open
+ bool invOpening = false; //is the opening animation playing
+ bool invHover = false; //are we using the fancy hover inventory
+ bool selected = false; //used in hover inventory to show which item has been selected
+ bool mouseSel = false; //the location of the temperary selection for the hover inv
+ bool usingi = false; //bool used to tell if inventory owner is using selected item
+
+ Inventory(unsigned int s); // Creates an inventory of size 's'
+ ~Inventory(void); // Free's allocated memory
+
+ int useCurrent();
+ void currentAddInteract(Entity* e);
+ void currentAddInteract(std::vector<Entity*> e);
+
+ int addItem(std::string name,uint count);
+ int takeItem(std::string name,uint count);
+ int hasItem(std::string name);
+
+ int useItem(void);
+ bool detectCollision(vec2,vec2);
+
+ void setSelection(unsigned int s);
+ void setSelectionUp();
+ void setSelectionDown();
+
+ void draw(void); // Draws a text list of items in this inventory (should only be called for the player for now)
+
+ const Item* getCurrentItem(void);
+};
+
+void initInventorySprites(void);
+void destroyInventory(void);
+
+const char *getItemTexturePath(std::string name);
+GLuint getItemTexture(std::string name);
+float getItemWidth(std::string name);
+float getItemHeight(std::string name);
+
+#include <entityx/entityx.h>
+
+class InventorySystem : public entityx::System<InventorySystem>, public entityx::Receiver<InventorySystem> {
+public:
+ void update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) override;
+
+ void configure(entityx::EventManager &em);
+ void receive(const MouseScrollEvent &mse);
+};
+
+#endif // INVENTORY_H
+++ /dev/null
-#ifndef MOB_H_
-#define MOB_H_
-
-#include <forward_list>
-#include <tuple>
-
-#include <common.hpp>
-#include <entities.hpp>
-#include <gametime.hpp>
-#include <ui.hpp>
-#include <save_util.hpp>
-
-// local library headers
-#include <tinyxml2.h>
-using namespace tinyxml2;
-
-extern Player *player;
-extern std::string currentXML;
-
-using Drop = std::tuple<std::string, unsigned int, float>;
-
-class Mob : public Entity {
-protected:
- XMLElement *xmle;
- std::forward_list<Drop> drop;
-
- unsigned int actCounter;
- unsigned int actCounterInitial;
- bool ridable;
-public:
- Entity *rider;
- bool aggressive;
- std::string heyid;
-
- Mob(void);
- ~Mob(void);
-
- void wander(void);
- void ride(Entity *e);
- virtual void act(void) =0;
-
- virtual void onHit(unsigned int) =0;
- virtual void onDeath(void);
-
- virtual bool bindTex(void) =0;
-};
-
-constexpr Mob *Mobp(Entity *e) {
- return (Mob *)e;
-}
-
-class Page : public Mob {
-private:
- std::string cId, cValue;
- std::string pageTexPath;
- GLuint pageTexture;
-public:
- Page(void);
-
- void act(void);
- void onHit(unsigned int);
- bool bindTex(void);
- void createFromXML(XMLElement *e, World *w) final;
- void saveToXML(void) final;
-};
-
-class Door : public Mob {
-public:
- Door(void);
-
- void act(void);
- void onHit(unsigned int);
- bool bindTex(void);
- void createFromXML(XMLElement *e, World *w) final;
- void saveToXML(void) final;
-};
-
-class Cat : public Mob {
-public:
- Cat(void);
-
- void act(void);
- void onHit(unsigned int);
- bool bindTex(void);
- void createFromXML(XMLElement *e, World *w) final;
- void saveToXML(void) final;
-};
-
-class Rabbit : public Mob {
-public:
- Rabbit(void);
-
- void act(void);
- void onHit(unsigned int);
- bool bindTex(void);
- void createFromXML(XMLElement *e, World *w) final;
- void saveToXML(void) final;
-};
-
-class Bird : public Mob {
-private:
- float initialY;
-public:
- Bird(void);
-
- void act(void);
- void onHit(unsigned int);
- bool bindTex(void);
- void createFromXML(XMLElement *e, World *w) final;
- void saveToXML(void) final;
-};
-
-class Trigger : public Mob {
-private:
- std::string id;
- bool triggered;
-public:
- bool notext;
-
- Trigger(void);
-
- void act(void);
- void onHit(unsigned int);
- bool bindTex(void);
- void createFromXML(XMLElement *e, World *w) final;
- void saveToXML(void) final;
-};
-
-class Chest : public Mob {
-public:
- Chest(void);
-
- void act(void);
- void onHit(unsigned int);
- bool bindTex(void);
- void createFromXML(XMLElement *e, World *w) final;
- void saveToXML(void) final;
-};
-
-#endif // MOB_H_
--- /dev/null
+#ifndef MOB_H_
+#define MOB_H_
+
+#include <forward_list>
+#include <tuple>
+
+#include <common.hpp>
+#include <entities.hpp>
+#include <gametime.hpp>
+#include <ui.hpp>
+#include <save_util.hpp>
+
+// local library headers
+#include <tinyxml2.h>
+using namespace tinyxml2;
+
+extern Player *player;
+extern std::string currentXML;
+
+using Drop = std::tuple<std::string, unsigned int, float>;
+
+class Mob : public Entity {
+protected:
+ XMLElement *xmle;
+ std::forward_list<Drop> drop;
+
+ unsigned int actCounter;
+ unsigned int actCounterInitial;
+ bool ridable;
+public:
+ Entity *rider;
+ bool aggressive;
+ std::string heyid;
+
+ Mob(void);
+ ~Mob(void);
+
+ void wander(void);
+ void ride(Entity *e);
+ virtual void act(void) =0;
+
+ virtual void onHit(unsigned int) =0;
+ virtual void onDeath(void);
+
+ virtual bool bindTex(void) =0;
+};
+
+constexpr Mob *Mobp(Entity *e) {
+ return (Mob *)e;
+}
+
+class Page : public Mob {
+private:
+ std::string cId, cValue;
+ std::string pageTexPath;
+ GLuint pageTexture;
+public:
+ Page(void);
+
+ void act(void);
+ void onHit(unsigned int);
+ bool bindTex(void);
+ void createFromXML(XMLElement *e, World *w) final;
+ void saveToXML(void) final;
+};
+
+class Door : public Mob {
+public:
+ Door(void);
+
+ void act(void);
+ void onHit(unsigned int);
+ bool bindTex(void);
+ void createFromXML(XMLElement *e, World *w) final;
+ void saveToXML(void) final;
+};
+
+class Cat : public Mob {
+public:
+ Cat(void);
+
+ void act(void);
+ void onHit(unsigned int);
+ bool bindTex(void);
+ void createFromXML(XMLElement *e, World *w) final;
+ void saveToXML(void) final;
+};
+
+class Rabbit : public Mob {
+public:
+ Rabbit(void);
+
+ void act(void);
+ void onHit(unsigned int);
+ bool bindTex(void);
+ void createFromXML(XMLElement *e, World *w) final;
+ void saveToXML(void) final;
+};
+
+class Bird : public Mob {
+private:
+ float initialY;
+public:
+ Bird(void);
+
+ void act(void);
+ void onHit(unsigned int);
+ bool bindTex(void);
+ void createFromXML(XMLElement *e, World *w) final;
+ void saveToXML(void) final;
+};
+
+class Trigger : public Mob {
+private:
+ std::string id;
+ bool triggered;
+public:
+ bool notext;
+
+ Trigger(void);
+
+ void act(void);
+ void onHit(unsigned int);
+ bool bindTex(void);
+ void createFromXML(XMLElement *e, World *w) final;
+ void saveToXML(void) final;
+};
+
+class Chest : public Mob {
+public:
+ Chest(void);
+
+ void act(void);
+ void onHit(unsigned int);
+ bool bindTex(void);
+ void createFromXML(XMLElement *e, World *w) final;
+ void saveToXML(void) final;
+};
+
+#endif // MOB_H_
+++ /dev/null
-/** @file Quest.h\r
- * @brief The quest handling system.\r
- *\r
- * This file contains Quest and QuestHandler, used to manage quests inside the\r
- * game.\r
- */\r
-\r
-#ifndef QUEST_H\r
-#define QUEST_H\r
-\r
-#include <string>\r
-\r
-#include <inventory.hpp>\r
-\r
-/**\r
- * When defined, DEBUG allows extra messages to be printed to the terminal for\r
- * debugging purposes.\r
- */\r
-\r
-#define DEBUG\r
-\r
-typedef struct {\r
- std::string title;\r
- std::string desc;\r
- std::pair<std::string, uint> reward;\r
- std::vector<std::pair<std::string, int>> need;\r
-} Quest;\r
-\r
-/**\r
- * The Quest Handler class.\r
- *\r
- * This class handles quests, including the assigning, dropping, and completing\r
- * of the quests.\r
- */\r
-\r
-class QuestHandler {\r
-public:\r
- std::vector<Quest>current;\r
-\r
- /**\r
- * Adds a quest to the current quest vector by its title.\r
- */\r
-\r
- int assign(std::string title,std::string desc,std::string req);\r
-\r
- /**\r
- * Drops a quest through its title.\r
- */\r
-\r
- int drop(std::string title);\r
-\r
- /**\r
- * Finishes a quest through it's title, also giving a pointer to the Entity\r
- * that gave the quest originally.\r
- */\r
-\r
- int finish(std::string t);\r
-\r
- /**\r
- * Returns true if this handler is currently taking the quest.\r
- */\r
-\r
- bool hasQuest(std::string t);\r
-};\r
-\r
-#endif // QUEST_H\r
--- /dev/null
+/** @file Quest.h\r
+ * @brief The quest handling system.\r
+ *\r
+ * This file contains Quest and QuestHandler, used to manage quests inside the\r
+ * game.\r
+ */\r
+\r
+#ifndef QUEST_H\r
+#define QUEST_H\r
+\r
+#include <string>\r
+\r
+#include <inventory.hpp>\r
+\r
+/**\r
+ * When defined, DEBUG allows extra messages to be printed to the terminal for\r
+ * debugging purposes.\r
+ */\r
+\r
+#define DEBUG\r
+\r
+typedef struct {\r
+ std::string title;\r
+ std::string desc;\r
+ std::pair<std::string, uint> reward;\r
+ std::vector<std::pair<std::string, int>> need;\r
+} Quest;\r
+\r
+/**\r
+ * The Quest Handler class.\r
+ *\r
+ * This class handles quests, including the assigning, dropping, and completing\r
+ * of the quests.\r
+ */\r
+\r
+class QuestHandler {\r
+public:\r
+ std::vector<Quest>current;\r
+\r
+ /**\r
+ * Adds a quest to the current quest vector by its title.\r
+ */\r
+\r
+ int assign(std::string title,std::string desc,std::string req);\r
+\r
+ /**\r
+ * Drops a quest through its title.\r
+ */\r
+\r
+ int drop(std::string title);\r
+\r
+ /**\r
+ * Finishes a quest through it's title, also giving a pointer to the Entity\r
+ * that gave the quest originally.\r
+ */\r
+\r
+ int finish(std::string t);\r
+\r
+ /**\r
+ * Returns true if this handler is currently taking the quest.\r
+ */\r
+\r
+ bool hasQuest(std::string t);\r
+};\r
+\r
+#endif // QUEST_H\r
// local game headers
#include <common.hpp>
#include <config.hpp>
-#include <entities.hpp>
-#include <inventory.hpp>
+//#include <inventory.hpp>
#include <ui_menu.hpp>
-#include <ui_action.hpp>
+//#include <ui_action.hpp>
// local library headers
#include <SDL2/SDL_opengl.h>
extern bool posFlag;
extern unsigned char dialogOptChosen;
- extern unsigned char merchOptChosen;
extern bool dialogBoxExists;
extern bool dialogImportant;
extern bool dialogPassive;
void drawBox(vec2 c1, vec2 c2);
void drawNiceBox(vec2 c1, vec2 c2, float z);
void dialogBox(std::string name, std::string opt, bool passive, std::string text, ...);
- void merchantBox(const char *name,Trade trade,const char *opt,bool passive,const char *text,...);
- void merchantBox();
void closeBox();
void waitForDialog(void);
+++ /dev/null
-#ifndef ACTION_H_
-#define ACTION_H_
-
-#include <common.hpp>
-#include <ui.hpp>
-
-namespace ui {
- namespace action {
- extern bool make;
-
- // enables the action ui
- void enable(void);
- // disables the action ui
- void disable(void);
-
- // draws the action ui
- void draw(vec2 loc);
- }
-}
-
-#endif // ACTION_H_
--- /dev/null
+#ifndef ACTION_H_
+#define ACTION_H_
+
+#include <common.hpp>
+#include <ui.hpp>
+
+namespace ui {
+ namespace action {
+ extern bool make;
+
+ // enables the action ui
+ void enable(void);
+ // disables the action ui
+ void disable(void);
+
+ // draws the action ui
+ void draw(vec2 loc);
+ }
+}
+
+#endif // ACTION_H_
ui::putStringCentered(offset.x, top_y - 40, "Current Quests:");
- auto y = top_y - 100;
+ /*auto y = top_y - 100;
const auto x = offset.x - 180;
for (const auto &q : player->qh.current) {
ui::putText(x, y, q.title.c_str());
y -= 20;
ui::putText(x + 40, y, q.desc.c_str());
y -= 40;
- }
+ }*/
std::swap(textWrap, ui::textWrapLimit);
}
// local game includes
#include <common.hpp>
-#include <entities.hpp>
#include <coolarray.hpp>
+#include <events.hpp>
+#include <texture.hpp>
+#include <tinyxml2.h>
+using namespace tinyxml2;
+
/**
* The background type enum.
* This enum contains all different possibilities for world backgrounds; used
unsigned char groundColor; /**< a value that affects the ground's color */
} WorldData;
-/**
- * Contains info necessary for switching worlds.
- * This pair contains a pointer to the new world, and the new set of
- * coordinates the player should be at in that world.
- */
-using WorldSwitchInfo = std::pair<World *, vec2>;
-
/**
* Alters how bright world elements are drawn.
* This value is based off of the current time of day (tick count), set in
*/
constexpr const unsigned int INDOOR_FLOOR_HEIGHT = (INDOOR_FLOOR_HEIGHTT + INDOOR_FLOOR_THICKNESS);
-/**
- * The village class.
- * This class defines an area in a world that is considered to be a village,
- * and provides a welcome message when the player enters the area.
- */
-class Village {
-public:
- /**
- * The name of the village.
- */
- std::string name;
-
- /**
- * The start and end coordinates of the village.
- */
- vec2 start, end;
-
- /**
- * A "player in village" flag.
- * This flag is used to trigger displaying the welcome message.
- */
- bool in;
-
- /**
- * Constructs a village with the given name, inside the given world.
- */
- Village(std::string meme, World *w);
-
- /**
- * Destructs the village.
- */
- ~Village(void){}
-};
-
-
#include <entityx/entityx.h>
constexpr const char* WorldWeatherString[3] = {
"Snowy"
};
+struct WorldData2 {
+ // data
+ std::vector<WorldData> data;
+ float startX;
+
+ // indoor
+ bool indoor;
+ float indoorWidth;
+ GLuint indoorTex;
+
+ // links
+ std::string toLeft, toRight;
+
+ // style
+ WorldBGType style;
+ std::string styleFolder;
+ std::vector<std::string> sTexLoc;
+
+ // music
+ std::string bgm;
+
+ // village
+ float villageStart, villageEnd;
+};
+
class WorldSystem : public entityx::System<WorldSystem>, public entityx::Receiver<WorldSystem> {
private:
- World *world;
- World *outside;
+ WorldData2 world;
WorldWeather weather;
Mix_Music *bgmObj;
- std::string bgmObjFile;
std::vector<std::string> bgFiles;
TextureIterator bgTex;
+ XMLDocument xmlDoc;
+
public:
explicit WorldSystem(void);
~WorldSystem(void);
ev.subscribe<BGMToggleEvent>(*this);
}
+ inline float getWidth(void) const
+ { return world.startX * -2.0f; }
+
void receive(const BGMToggleEvent &bte);
void update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) override;
void render(void);
- void setWorld(World *w);
-
inline const std::string getWeatherStr(void) const
{ return WorldWeatherString[static_cast<int>(weather)]; }
void setWeather(const std::string &s);
- void singleDetect(Entity *e, entityx::TimeDelta dt);
void detect(entityx::TimeDelta dt);
- void detect2(entityx::TimeDelta dt);
-
- void enterWorld(World *w);
- void leaveWorld(void);
-};
-
-
-/**
- * The world class.
- * This class handles entity creation, management, and deletion. Most
- * world-related operations have to be done through this class, such as
- * drawing.
- */
-class World {
-private:
- bool m_Indoor;
-
-public:
-
- float HouseWidth;
- GLuint houseTex;
-
- inline bool isIndoor(void) const
- { return m_Indoor; }
-
- WorldBGType bgType;
-
- std::string styleFolder;
+ void goWorldLeft(void) {}
+ void goWorldRight(void) {}
- /**
- * An array of all the world's ground data, populated through
- * World::generate().
- * @see generate()
- */
- std::vector<WorldData> worldData;
-
- /**
- * Contains the size of the 'worldData' array.
- */
- unsigned int lineCount;
-
- /**
- * The starting x-coordinate of the world.
- */
- float worldStart;
-
- /**
- * The path to the XML file of the world to the left.
- *
- * @see setToLeft()
- */
- std::string toLeft;
-
- /**
- * The path to the XML file of the world to the right.
- *
- * @see setToRight()
- */
- std::string toRight;
-
- /**
- * A vector of paths for the structure textures.
- * The appearance of structures depends on the world's theme.
- *
- * @see setStyle()
- */
- std::vector<std::string> sTexLoc;
-
- /**
- * Contains randomly generated coordinates for stars.
- */
- std::vector<vec2> star;
-
- /**
- * A vector of all light elements in the world.
- *
- * @see addLight()
- * @see getLastLight()
- */
- std::vector<Light> light;
-
- /**
- * A vector of all villages in the world.
- *
- * @see addVillage()
- */
- std::vector<Village> village;
-
- std::vector<Entity *> entityPending;
-
- /**
- * Destroys entities and clears vectors that contain them.
- * This function is only called in the world destructor.
- */
- void deleteEntities(void);
-
- /**
- * The filename of the world's BGM file.
- *
- * @see setBGM()
- */
- std::string bgm;
-
- CoolArray<Particles> particles;
-
- /**
- * A vector of pointers to all entities from the other vectors.
- * This is used to mass-manage entities, or operate on entities
- * outside of what the world does.
- *
- * @see getNearInteractable()
- */
- std::vector<Entity *> entity;
-
- /**
- * Constructs the world, resets variables.
- */
- World(bool indoor = false);
-
- /**
- * Destructs the world, frees memory.
- */
- virtual ~World(void);
-
- /**
- * Generates a world of the specified width.
- * This will populate the 'worldData' array and create star coordinates.
- * It's necessary to call this function to actually use the world.
- */
- void generate(int width);
-
- /**
- * Draws everything the world handles to the screen (and the player).
- * Drawing is based off of the player so that off-screen elements are not
- * drawn.
- */
- virtual void draw(Player *p);
-
- /**
- * Gets the width of the world, presumably in pixels.
- * TODO
- */
- int getTheWidth(void) const;
-
- /**
- * Gets the starting x-coordinate of the world.
- *
- * @see worldStart
- */
- float getWorldStart(void) const;
-
- inline unsigned int getEntityCount(void) const {
- return entity.size();
- }
+ // worlddata2 stuff
+ WorldData2 worldData;
- /**
- * Gets a pointer to the most recently created light.
- * This is used to update properties of the light outside of the
- * world class.
- */
- Light& getLastLight(void);
+ void generate(unsigned int width = 0);
+ void addHole(const unsigned int& start, const unsigned int& end);
+ void addHill(const ivec2& peak, const unsigned int& width);
- /**
- * Gets a pointer ot the most recently created mob.
- * This is used to update properties of the mob outside of the
- * world class.
- */
- Mob* getLastMob(void);
-
- /**
- * Finds the entity nearest to the provided one.
- */
- Entity* getNearInteractable(Entity &e);
-
- /**
- * Finds the mob nearest to the given entity.
- */
- Mob* getNearMob(Entity &e);
-
- /**
- * Gets the coordinates of the `index`th structure.
- */
- vec2 getStructurePos(int index);
-
- /**
- * Gets the texture path of the `index`th structure
- */
- std::string getSTextureLocation(unsigned int index) const;
-
- // saves the world's data to an XML file, either the one provided or the current path
- void save(const std::string& s="");
-
- // sets the world's background theme
- void setBackground(WorldBGType bgt);
-
- // sets the folder to collect entity textures from
- void setStyle(std::string pre);
-
- // gets the string that represents the current weather
- std::string getWeatherStr(void) const;
- const WorldWeather& getWeatherId(void) const;
-
- // sets the weatherrrr
- void setWeather(const std::string& w);
-
- // sets / gets pathnames of XML files for worlds to the left and right
- std::string setToLeft(std::string file);
- std::string setToRight(std::string file);
- std::string getToLeft(void) const;
- std::string getToRight(void) const;
-
- // attempts to enter the left/right adjacent world, returning either that world or this
- WorldSwitchInfo goWorldLeft(Player *p);
- WorldSwitchInfo goWorldRight(Player *p);
-
- /**
- * Attempts to move an NPC to the left adjacent world, returning true on success.
- */
- bool goWorldLeft(NPC *e);
-
- /**
- * Attempts to move an NPC to the world to the right, returning true on success.
- */
- bool goWorldRight(NPC *e);
-
- // attempts to enter a structure that the player would be standing in front of
- WorldSwitchInfo goInsideStructure(Player *p);
-
- /**
- * Adopts an NPC from another world, taking its ownership.
- */
- void adoptNPC(NPC *e);
-
- /**
- * Adopts a mob from another world, taking its ownership.
- */
- void adoptMob(Mob *e);
-
- // adds a hole at the specified start and end x-coordinates
- void addHole(unsigned int start,unsigned int end);
-
- // adds a hill that peaks at the given coordinate and is `width` HLINEs wide
- void addHill(ivec2 peak, unsigned int width);
-
- // functions to add entities to the world
- void addLight(vec2 xy, float radius, Color color);
-
- void addMerchant(float x, float y, bool housed);
-
- void addMob(Mob *m, vec2 coord);
-
- 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(Structures *s);
-
- Village *addVillage(std::string name, World *world);
-};
-
-/**
- * The arena class - creates an arena.
- *
- * This world, when created, expects a pointer to a Mob. This mob will be
- * transported to a temporary world with the player, and the Mob will be
- * killed upon exiting the arena.
- */
-
-class Arena : public World {
-private:
-
- // the mob that the player is fighting
- Mob *mmob;
-
-public:
-
- // creates the arena with the world being left for it
- Arena(void);
-
- // frees memory
- ~Arena(void);
-
- // starts a new fight??
- void fight(World *leave, const Player *p, Mob *m);
-
- // attempts to exit the arena, returning what world the player should be in
- WorldSwitchInfo exitArena(Player *p);
+ bool save(const std::string& file);
+ void load(const std::string& file);
};
/**
*/
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;
-}
-
#endif // WORLD_H
// local game includes
#include <common.hpp>
#include <config.hpp>
-#include <entities.hpp>
+//#include <entities.hpp>
#include <world.hpp>
#include <ui.hpp>
#include <gametime.hpp>
** Variables section
** --------------------------------------------------------------------------*/
-// world objects for the current world and the two that are adjacent
-World *currentWorld = NULL,
- *currentWorldToLeft = NULL,
- *currentWorldToRight = NULL;
-
-// an arena for fightin'
-Arena *arena = nullptr;
-
// the currently used folder to grab XML files
std::string xmlFolder;
// the current menu
Menu *currentMenu;
-// the player object
-Player *player;
-
// keeps a simple palette of colors for single-color draws
GLuint colorIndex;
game::briceUpdate();
// load sprites used in the inventory menu. See src/inventory.cpp
- initInventorySprites();
+ //initInventorySprites();
// load mouse texture, and other inventory textures
mouseTex = Texture::loadTexture("assets/mouse.png");
- player = new Player();
- player->sspawn(0,100);
+ //player = new Player();
+ //player->sspawn(0,100);
// get a world
if (xmlFolder.empty())
goto EXIT_ROUTINE;
if (!worldActuallyUseThisXMLFile.empty()) {
- delete currentWorld;
- currentWorld = loadWorldFromXML(worldActuallyUseThisXMLFile);
- } else if (currentWorld == nullptr) {
-
+ game::engine.getSystem<WorldSystem>()->load(worldActuallyUseThisXMLFile);
+ } else {
// load the first valid XML file for the world
for (const auto &xf : xmlFiles) {
if (xf[0] != '.') {
// read it in
std::cout << "File to load: " << xf << '\n';
- currentWorld = loadWorldFromXML(xf);
+ game::engine.getSystem<WorldSystem>()->load(xf);
break;
}
}
}
- // make sure the world was made
- if (currentWorld == nullptr)
- UserError("Plot twist: The world never existed...?");
-
ui::menu::init();
- game::events.emit<BGMToggleEvent>(currentWorld->bgm);
-
- game::engine.getSystem<WorldSystem>()->setWorld(currentWorld);
-
- // spawn the arena
- arena = new Arena();
- arena->setStyle("");
- arena->setBackground(WorldBGType::Forest);
- arena->bgm = "assets/music/embark.wav";
+// game::events.emit<BGMToggleEvent>(currentWorld->bgm);
// the main loop, in all of its gloriousness..
std::thread([&]{
std::thread([&]{
while (game::engine.shouldRun()) {
fps = 1000 / game::time::getDeltaTime();
- debugY = player->loc.y;
+// debugY = player->loc.y;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
Mix_HaltMusic();
Mix_CloseAudio();
- destroyInventory();
+// destroyInventory();
ui::destroyFonts();
Texture::freeTextures();
// close up the game stuff
- currentWorld->save();
- delete arena;
- //delete currentWorld;
+// currentWorld->save();
game::engine.getSystem<WindowSystem>()->die();
return 0; // Calls everything passed to atexit
}
-extern std::vector<NPC *> aipreload;
-
void mainLoop(void){
game::time::mainLoopHandler();
if (currentMenu) {
return;
} else {
- // Flush preloaded AI functions if necessary
- if (!ui::dialogBoxExists) {
- while (!aipreload.empty()) {
- aipreload.front()->addAIFunc(false);
- aipreload.erase(std::begin(aipreload));
- }
- }
-
if (game::time::tickHasPassed())
logic();
const auto SCREEN_WIDTH = game::SCREEN_WIDTH;
const auto SCREEN_HEIGHT = game::SCREEN_HEIGHT;
- offset.x = player->loc.x + player->width / 2;
+// offset.x = player->loc.x + player->width / 2;
+
+ auto worldWidth = game::engine.getSystem<WorldSystem>()->getWidth();
// ortho x snapping
- if (currentWorld->getTheWidth() < (int)SCREEN_WIDTH)
+ if (worldWidth < (int)SCREEN_WIDTH)
offset.x = 0;
- else if (offset.x - SCREEN_WIDTH / 2 < currentWorld->getTheWidth() * -0.5f)
- offset.x = ((currentWorld->getTheWidth() * -0.5f) + SCREEN_WIDTH / 2);
- else if (offset.x + SCREEN_WIDTH / 2 > currentWorld->getTheWidth() * 0.5f)
- offset.x = ((currentWorld->getTheWidth() * 0.5f) - SCREEN_WIDTH / 2);
+ else if (offset.x - SCREEN_WIDTH / 2 < worldWidth * -0.5f)
+ offset.x = ((worldWidth * -0.5f) + SCREEN_WIDTH / 2);
+ else if (offset.x + SCREEN_WIDTH / 2 > worldWidth * 0.5f)
+ offset.x = ((worldWidth * 0.5f) - SCREEN_WIDTH / 2);
// ortho y snapping
- offset.y = std::max(player->loc.y + player->height / 2, SCREEN_HEIGHT / 2.0f);
+ offset.y = /*std::max(player->loc.y + player->height / 2,*/ SCREEN_HEIGHT / 2.0f; /*);*/
// "setup"
glm::mat4 projection = glm::ortho(floor(offset.x - SCREEN_WIDTH / 2), // left
// draw the world and player
game::engine.getSystem<WorldSystem>()->render();
- currentWorld->draw(player);
// draw the player's inventory
- player->inv->draw();
+ //player->inv->draw();
// draw the fade overlay
ui::drawFade();
ui::putText(offset.x-SCREEN_WIDTH/2, (offset.y+SCREEN_HEIGHT/2)-ui::fontSize,
"fps: %d\ngrounded:%d\nresolution: %ux%u\nentity cnt: %d\nloc: (%+.2f, %+.2f)\nticks: %u\nvolume: %f\nweather: %s\nxml: %s",
fps,
- player->ground,
+ 0,//player->ground,
SCREEN_WIDTH, // Window dimensions
SCREEN_HEIGHT, //
- currentWorld->entity.size(),// Size of entity array
- player->loc.x, // The player's x coordinate
+ 0,//currentWorld->entity.size(),// Size of entity array
+ 0,//player->loc.x, // The player's x coordinate
debugY, // The player's y coordinate
game::time::getTickCount(),
game::config::VOLUME_MASTER,
game::engine.getSystem<WorldSystem>()->getWeatherStr().c_str(),
- currentXML.c_str()
+ ""//currentXML.c_str()
);
// draw tracer lines if desired
- static const GLuint tracerText = Texture::genColor(Color(100,100,255));
- if (ui::posFlag) {
+ //static const GLuint tracerText = Texture::genColor(Color(100,100,255));
+ /*if (ui::posFlag) {
GLfloat *tpoint = new GLfloat[currentWorld->getEntityCount() * 2 * 5];
auto tp = tpoint;
Render::textShader.unuse();
delete[] tpoint;
- }
+ }*/
}
}
void logic(){
- static bool NPCSelected = false;
- static bool ObjectSelected = false;
+// static bool NPCSelected = false;
+// static bool ObjectSelected = false;
// exit the game if the player falls out of the world
- if (player->loc.y < 0)
- game::endGame();
+ /*if (player->loc.y < 0)
+ game::endGame();*/
- if (player->inv->usingi) {
+ /*if (player->inv->usingi) {
for (auto &e : currentWorld->entity) {
if (player->inv->usingi && !e->isHit() &&
player->inv->detectCollision(vec2 { e->loc.x, e->loc.y }, vec2 { e->loc.x + e->width, e->loc.y + e->height})) {
}
}
player->inv->usingi = false;
- }
+ }*/
- for (auto &e : currentWorld->entity) {
+ /*for (auto &e : currentWorld->entity) {
if (e->isAlive() && ((e->type == NPCT) || (e->type == MERCHT) || (e->type == OBJECTT))) {
if (e->type == OBJECTT && ObjectSelected) {
e->near = false;
e->near = player->isNear(e);
e->wander();
}
- }
+ }*/
// calculate the world shading value
worldShade = 50 * sin((game::time::getTickCount() + (DAY_CYCLE / 2)) / (DAY_CYCLE / PI));
ui::fadeUpdate();
// create weather particles if necessary
- auto weather = game::engine.getSystem<WorldSystem>()->getWeatherId();
+ /*auto weather = game::engine.getSystem<WorldSystem>()->getWeatherId();
+ auto worldWidth = game::engine.getSystem<WorldSystem>()->getWidth();
if (weather == WorldWeather::Rain) {
for (unsigned int r = (randGet() % 25) + 11; r--;) {
- currentWorld->addParticle(randGet() % currentWorld->getTheWidth() - (currentWorld->getTheWidth() / 2),
+ currentWorld->addParticle(randGet() % worldWidth - (worldWidth / 2),
offset.y + game::SCREEN_HEIGHT / 2,
HLINES(1.25), // width
HLINES(1.25), // height
}
} else if (weather == WorldWeather::Snowy) {
for (unsigned int r = (randGet() % 25) + 11; r--;) {
- currentWorld->addParticle(randGet() % currentWorld->getTheWidth() - (currentWorld->getTheWidth() / 2),
+ currentWorld->addParticle(randGet() % worldWidth - (worldWidth / 2),
offset.y + game::SCREEN_HEIGHT / 2,
HLINES(1.25), // width
HLINES(1.25), // height
0 // no gravity, no bounce
);
}
- }
+ }*/
// increment game ticker
game::time::tick();
- NPCSelected = false;
- ObjectSelected = false;
+ //NPCSelected = false;
+ //ObjectSelected = false;
}
#include <config.hpp>
#include <world.hpp>
#include <ui.hpp>
-#include <inventory.hpp>
-#include <entities.hpp>
+//#include <inventory.hpp>
#include <window.hpp>
extern World *currentWorld;
systems.add<WindowSystem>();
systems.add<InputSystem>();
- systems.add<InventorySystem>();
+// systems.add<InventorySystem>();
systems.add<WorldSystem>();
- systems.add<PlayerSystem>(&player);
+// systems.add<PlayerSystem>(&player);
systems.configure();
void Engine::update(entityx::TimeDelta dt)
{
systems.update<InputSystem>(dt);
- systems.update<InventorySystem>(dt);
- systems.update<PlayerSystem>(dt);
+// systems.update<InventorySystem>(dt);
+// systems.update<PlayerSystem>(dt);
systems.update<WorldSystem>(dt);
}
+++ /dev/null
-#include <entities.hpp>
-
-#include <istream>
-#include <sstream>
-#include <fstream>
-
-#include <ui.hpp>
-#include <world.hpp>
-#include <gametime.hpp>
-#include <brice.hpp>
-
-#include <render.hpp>
-#include <engine.hpp>
-
-///NEW
-#include <components.hpp>
-#include <entityx/entityx.h>
-///OLD
-
-extern std::istream *names;
-
-extern Player *player; // main.cpp
-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;
-
-// the size of the player's inventory
-const unsigned int PLAYER_INV_SIZE = 43;
-// the size of an NPC's inventory
-const unsigned int NPC_INV_SIZE = 3;
-
-static std::vector<std::string> randomDialog (readFileA("assets/dialog_en-us"));
-
-
-void PlayerSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt)
-{
- (void)en;
- (void)ev;
- (void)dt;
-
- if (!m_MoveLeft && !m_MoveRight)
- (*m_Player)->vel.x = 0;
-}
-
-void PlayerSystem::configure(entityx::EventManager &ev)
-{
- ev.subscribe<KeyDownEvent>(*this);
- ev.subscribe<KeyUpEvent>(*this);
-}
-
-extern World *currentWorldToLeft;
-extern World *currentWorldToRight;
-extern bool gameRunning;
-extern bool inBattle;
-
-void PlayerSystem::receive(const KeyUpEvent &kue)
-{
- auto p = *m_Player;
- auto kc = kue.keycode;
-
- if (kc == SDLK_ESCAPE) {
- ui::menu::toggle();
- p->save();
- } else if (kc == getControl(1)) {
- m_MoveLeft = false;
- } else if (kc == getControl(2)) {
- m_MoveRight = false;
- } else if (kc == getControl(3) || kc == getControl(4)) {
- player->speed = 1;
- } else if (kc == getControl(5)) {
- if (p->inv->invHover) {
- p->inv->invHover = false;
- } else {
- if (!p->inv->selected)
- p->inv->invOpening ^= true;
- else
- p->inv->selected = false;
-
- p->inv->mouseSel = false;
- }
-
- // disable action ui
- ui::action::disable();
- }
-}
-
-void PlayerSystem::receive(const KeyDownEvent &kde)
-{
- auto p = *m_Player;
- auto kc = kde.keycode;
-
- auto worldSwitch = [&](const WorldSwitchInfo& wsi){
- player->canMove = false;
- ui::toggleBlackFast();
- ui::waitForCover();
- game::events.emit<BGMToggleEvent>(wsi.first->bgm, wsi.first);
- std::tie(currentWorld, player->loc) = wsi; // using p causes segfault
- game::engine.getSystem<WorldSystem>()->setWorld(currentWorld);
- ui::toggleBlackFast();
- ui::waitForUncover();
- player->canMove = true; // using p causes segfault
- };
-
- if ((kc == SDLK_SPACE) && (game::canJump & p->ground)) {
- p->loc.y += HLINES(2);
- p->vel.y = .4;
- p->ground = false;
- }
-
- if (!ui::dialogBoxExists || ui::dialogPassive) {
- if (kc == getControl(0)) {
- if (inBattle) {
- std::thread([&](void){
- auto thing = dynamic_cast<Arena *>(currentWorld)->exitArena(p);
- if (thing.first != currentWorld)
- worldSwitch(thing);
- }).detach();
- } else if (!ui::fadeIntensity) {
- std::thread([&](void){
- auto thing = currentWorld->goInsideStructure(p);
- if (thing.first != currentWorld)
- worldSwitch(thing);
- }).detach();
- }
- } else if (kc == getControl(1)) {
- if (!ui::fadeEnable) {
- p->vel.x = -PLAYER_SPEED_CONSTANT;
- if (std::stoi(game::getValue("Slow")) == 1)
- p->vel.x /= 2.0f;
- p->left = m_MoveLeft = true;
- p->right = m_MoveRight = false;
- if (currentWorldToLeft) {
- std::thread([&](void){
- auto thing = currentWorld->goWorldLeft(p);
- if (thing.first != currentWorld)
- worldSwitch(thing);
- }).detach();
- }
- }
- } else if (kc == getControl(2)) {
- if (!ui::fadeEnable) {
- p->vel.x = PLAYER_SPEED_CONSTANT;
- if (std::stoi(game::getValue("Slow")) == 1)
- p->vel.x /= 2.0f;
- p->right = m_MoveRight = true;
- p->left = m_MoveLeft = false;
- if (currentWorldToRight) {
- std::thread([&](void){
- auto thing = currentWorld->goWorldRight(p);
- if (thing.first != currentWorld)
- worldSwitch(thing);
- }).detach();
- }
- }
- } else if (kc == getControl(3)) {
- if (game::canSprint)
- p->speed = 2.0f;
- } else if (kc == getControl(4)) {
- p->speed = .5;
- } else if (kc == getControl(5)) {
- /*static int heyOhLetsGo = 0;
-
- //edown = true;
-
- // start hover counter?
- if (!heyOhLetsGo) {
- heyOhLetsGo = game::time::getTickCount();
- p->inv->mouseSel = false;
- }
-
- // run hover thing
- if (game::time::getTickCount() - heyOhLetsGo >= 2 && !(p->inv->invOpen) && !(p->inv->selected)) {
- p->inv->invHover = true;
-
- // enable action ui
- ui::action::enable();
- }*/
- }
- } else if (kc == SDLK_DELETE) {
- game::endGame();
- } else if (kc == SDLK_t) {
- game::time::tick(50);
- }
-}
-
-
-void getRandomName(Entity *e)
-{
- auto names = readFileA("assets/names_en-us");
- auto name = names[randGet() % names.size()];
-
- // gender is a binary construct
- e->gender = (name[0] == 'm') ? MALE : FEMALE;
-
- e->name = &name[1];
-}
-
-Entity::Entity(void)
-{
- vel = 0;
- width = 0;
- height = 0;
- health = 0;
- maxHealth = 0;
- outnabout = 0;
- targetx = 0.9112001f;
-
- type = UNKNOWNT;
-
- // set flags
- alive = true;
- right = true;
- left = false;
- near = false;
- canMove = true;
- ground = false;
- forcedMove = false;
- z = 0.0f;
-
- // clear counters
- ticksToUse = 0;
- hitCooldown = 0;
-
- hitDuration = maxHitDuration = 0;
-
- inv = nullptr;
-}
-
-// spawns the entity you pass to it based off of coords and global entity settings
-void Entity::spawn(float x, float y)
-{
- loc.x = x;
- loc.y = y;
-
- if (health == 0 && maxHealth == 0)
- health = maxHealth = 1;
-
- // generate a name
- if (type == MOBT)
- name = "mob";
- else
- getRandomName(this);
-
- setCooldown(0);
-}
-
-void Entity::takeHit(unsigned int _health, unsigned int cooldown)
-{
- if (hitCooldown <= 1) {
- // modify variables
- health = fmax(health - _health, 0);
- forcedMove = true;
- hitCooldown = cooldown;
-
- hitDuration = maxHitDuration = 350.0f;
-
- // pushback
- vel.x = player->left ? -0.5f : 0.5f;
- vel.y = 0.2f;
- }
-}
-
-unsigned int Entity::coolDown()
-{
- return hitCooldown;
-}
-
-void Entity::setCooldown(unsigned int c)
-{
- hitCooldown = c;
-}
-
-void Entity::handleHits(void)
-{
- hitCooldown = fmax(static_cast<int>(hitCooldown - game::time::getDeltaTime()), 0);
- hitDuration = fmax(hitDuration - game::time::getDeltaTime(), 0);
-
- if (!forcedMove)
- return;
-
- // reduce knockback
- if ((vel.x > 0.0005f) || (vel.x < -0.0005f))
- vel.x *= 0.6f;
- else
- forcedMove = false;
-}
-
-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
-{
- return alive;
-}
-
-bool Entity::isHit(void) const
-{
- return forcedMove;
-}
-
-void Entity::moveTo(float dest_x)
-{
- targetx = dest_x;
-}
-
-Player::Player() : Entity()
-{
- width = HLINES(10);
- height = HLINES(16);
-
- type = PLAYERT; //set type to player
- subtype = 0;
- health = maxHealth = 100;
- speed = 1;
- canMove = true;
-
- tex = TextureIterator({"assets/player/playerk.png",
- "assets/player/playerk1.png",
- "assets/player/playerk2.png",
- "assets/player/playerk3.png",
- "assets/player/playerk4.png",
- "assets/player/playerk5.png",
- "assets/player/playerk6.png",
- "assets/player/playerk7.png",
- "assets/player/playerk8.png"
- });
-
- inv = new Inventory(PLAYER_INV_SIZE);
- dim2 tmpDim = Texture::imageDim(tex.getTexturePath(0));
- width = HLINES(tmpDim.x/2);
- height = HLINES(tmpDim.y/2);
-
- z = -2.0;
-}
-
-Player::~Player()
-{
- delete inv;
- delete &tex;
-}
-
-void Player::createFromXML(XMLElement *e, World *w=nullptr)
-{
- (void)e;
- (void)w;
-}
-
-void Player::saveToXML(void)
-{}
-
-NPC::NPC() : Entity()
-{
- width = HLINES(10);
- height = HLINES(16);
-
- type = NPCT; //sets type to npc
- subtype = 0;
-
- health = maxHealth = 100;
-
- maxHealth = health = 100;
- canMove = true;
-
- tex = TextureIterator({"assets/NPC.png"});
- inv = new Inventory(NPC_INV_SIZE);
-
- randDialog = randGet() % randomDialog.size();
- dialogIndex = 0;
- dialogCount = 0;
-
- dim2 tmpDim = Texture::imageDim(tex.getTexturePath(0));
- width = HLINES(tmpDim.x/2);
- height = HLINES(tmpDim.y/2);
-}
-
-NPC::~NPC()
-{
- delete inv;
-}
-
-void NPC::createFromXML(XMLElement *e, World *w=nullptr)
-{
- std::string npcname;
- bool dialog;
- unsigned int flooor;
-
- xmle = e;
- (void)w;
-
- // spawn at coordinates if desired
- E_LOAD_COORDS(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;
-
- // custom health value
- E_LOAD_HEALTH;
-
- // movemenet
- if (e->QueryBoolAttribute("canMove", &dialog) == XML_NO_ERROR)
- canMove = dialog;
-
- // dialog index
- if (e->QueryUnsignedAttribute("dindex", &flooor) == XML_NO_ERROR)
- dialogIndex = flooor;
-}
-
-void NPC::saveToXML(void)
-{
- E_SAVE_HEALTH;
- E_SAVE_COORDS;
- xmle->SetAttribute("dindex", dialogIndex);
-}
-
-Merchant::Merchant() : NPC()
-{
- width = HLINES(10);
- height = HLINES(16);
-
- type = MERCHT; //sets type to merchant
- subtype = 0;
-
- health = maxHealth = 100;
-
- canMove = true;
-
- trade.reserve(100);
- currTrade = 0;
-
- inside = nullptr;
-
- //tex = new Texturec(1,"assets/NPC.png");
- //inv = new Inventory(NPC_INV_SIZE);
- //inv = new Inventory(1);
-
- //randDialog = rand() % RAND_DIALOG_COUNT - 1;
- dialogIndex = 0;
-
- dim2 tmpDim = Texture::imageDim(tex.getTexturePath(0));
- width = HLINES(tmpDim.x/2);
- height = HLINES(tmpDim.y/2);
-}
-
-Merchant::~Merchant()
-{
-}
-
-void Merchant::saveToXML(void){}
-
-Structures::Structures() : Entity()
-{
- type = STRUCTURET;
- canMove = false;
- health = maxHealth = 1;
-}
-
-Structures::~Structures()
-{
-}
-
-extern std::string currentXMLRaw;
-
-void Structures::createFromXML(XMLElement *e, World *w)
-{
- float spawnx;
-
- if (e->QueryBoolAttribute("alive", &alive) == XML_NO_ERROR && !alive) {
- //die();
- return;
- }
-
- inWorld = w;
- inside = e->StrAttribute("inside");
-
- // edge
- if (!inside.empty()) {
- insideWorld = loadWorldFromXMLNoTakeover(inside);
- }
-
- textureLoc = e->StrAttribute("texture");
-
- insideTex = Texture::loadTexture(e->StrAttribute("insideTexture"));
-
- spawn(static_cast<BUILD_SUB>(e->UnsignedAttribute("type")),
- e->QueryFloatAttribute("spawnx", &spawnx) == XML_NO_ERROR ? spawnx : (randGet() % w->getTheWidth() / 2.0f),
- 100);
-
- xmle = e;
-}
-
-void Structures::saveToXML(void)
-{
- xmle->SetAttribute("alive", alive);
-}
-
-Object::Object()
-{
- type = OBJECTT;
-}
-
-Object::Object(std::string in, std::string pd)
-{
- iname = in;
-
- pickupDialog = pd;
- questObject = !pd.empty();
-
- type = OBJECTT;
- width = getItemWidth(in);
- height = getItemHeight(in);
-
- tex = TextureIterator({getItemTexturePath(in)});
-}
-
-Object::~Object()
-{
-}
-
-void Object::createFromXML(XMLElement *e, World *w=nullptr)
-{
- (void)e;
- (void)w;
-}
-
-void Object::saveToXML(void)
-{}
-
-void Object::reloadTexture(void)
-{
- tex = TextureIterator({getItemTexturePath(iname)});
- width = getItemWidth(iname);
- height = getItemHeight(iname);
-}
-
-bool Entity::isNear(const Entity *e) {
- return (e != nullptr) ? (pow(e->loc.x - loc.x, 2) + pow(e->loc.y - loc.y, 2) <= pow(HLINES(40), 2)) : false;
-}
-
-void NPC::drawThingy(void) const
-{
- if (dialogCount) {
- const auto w = width / 3;
- GLfloat tex_coord[] = {
- 0, 0, 1, 0, 1, 1,
- 1, 1, 0, 1, 0, 0
- };
- const GLfloat c[4] = {
- loc.x + w, loc.y + height, loc.x + w * 2, loc.y + height + w
- };
- GLfloat coords[] = {
- c[0], c[1], z, c[2], c[1], z, c[2], c[3], z,
- c[2], c[3], z, c[0], c[3], z, c[0], c[1], z
- };
-
- // TODO use texture made for this
- static GLuint thingyColor = Texture::genColor(Color(236, 238, 15));
-
- Render::worldShader.use();
- Render::worldShader.enable();
-
- glBindTexture(GL_TEXTURE_2D, thingyColor);
-
- glVertexAttribPointer(Render::worldShader.coord, 3, GL_FLOAT, GL_FALSE, 0, coords);
- glVertexAttribPointer(Render::worldShader.tex, 2, GL_FLOAT, GL_FALSE, 0, tex_coord);
- glDrawArrays(GL_TRIANGLES, 0, 6);
-
- Render::worldShader.disable();
- Render::worldShader.unuse();
- }
-}
-
-void Entity::draw(void)
-{
- GLfloat tex_coord[] = {0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
-
- 1.0, 1.0,
- 0.0, 1.0,
- 0.0, 0.0};
-
- GLfloat tex_coordL[] = {1.0, 0.0,
- 0.0, 0.0,
- 0.0, 1.0,
-
- 0.0, 1.0,
- 1.0, 1.0,
- 1.0, 0.0};
-
- GLfloat coords[] = {loc.x, loc.y, z,
- loc.x + width, loc.y, z,
- loc.x + width, loc.y + height, z,
-
- loc.x + width, loc.y + height, z,
- loc.x, loc.y + height, z,
- loc.x, loc.y, z};
-
-
- glActiveTexture(GL_TEXTURE0);
-
- if (!alive)
- return;
-
- if (type == NPCT) {
- NPCp(this)->drawThingy();
-
- if (gender == MALE)
- glColor3ub(255, 255, 255);
- else if (gender == FEMALE)
- glColor3ub(255, 105, 180);
- } else if (type == MOBT) {
- if (Mobp(this)->rider != nullptr) {
- Mobp(this)->rider->loc.x = loc.x + width * 0.25f;
- Mobp(this)->rider->loc.y = loc.y + height - HLINES(5);
- Mobp(this)->rider->vel.y = .12;
- Mobp(this)->rider->z = z + 0.01;
- }
- }
- switch(type) {
- case PLAYERT:
- static int texState = 0;
- if (speed && !(game::time::getTickCount() % ((2.0f/speed) < 1 ? 1 : (int)((float)2.0f/(float)speed)))) {
- if (++texState == 9)
- texState = 1;
- glActiveTexture(GL_TEXTURE0);
- tex(texState);
- }
- if (!ground) {
- glActiveTexture(GL_TEXTURE0);
- tex(0);
- } else if (vel.x) {
- glActiveTexture(GL_TEXTURE0);
- tex(texState);
- } else {
- glActiveTexture(GL_TEXTURE0);
- tex(0);
- }
- break;
- case MOBT:
- if (!Mobp(this)->bindTex())
- goto NOPE;
- break;
- case STRUCTURET:
- /* fall through */
- default:
- glActiveTexture(GL_TEXTURE0);
- tex(0);
- break;
- }
-
- Render::worldShader.use();
- // make the entity hit flash red
- if (maxHitDuration-hitDuration) {
- float flashAmt = 1-(hitDuration/maxHitDuration);
- glUniform4f(Render::worldShader.uniform[WU_tex_color], 1.0, flashAmt, flashAmt, 1.0);
- }
-
- glUniform1i(Render::worldShader.uniform[WU_texture], 0);
- Render::worldShader.enable();
-
- glVertexAttribPointer(Render::worldShader.coord, 3, GL_FLOAT, GL_FALSE, 0, coords);
- if (left)
- glVertexAttribPointer(Render::worldShader.tex, 2, GL_FLOAT, GL_FALSE, 0 ,tex_coordL);
- else
- glVertexAttribPointer(Render::worldShader.tex, 2, GL_FLOAT, GL_FALSE, 0 ,tex_coord);
- glDrawArrays(GL_TRIANGLES, 0, 6);
-
- glUniform4f(Render::worldShader.uniform[WU_tex_color], 1.0, 1.0, 1.0, 1.0);
-NOPE:
-if (near && type != MOBT)
- ui::putStringCentered(loc.x+width/2,loc.y-ui::fontSize-game::HLINE/2,name);
-if (health != maxHealth) {
-
- static GLuint frontH = Texture::genColor(Color(255,0,0));
- static GLuint backH = Texture::genColor(Color(150,0,0));
- glUniform1i(Render::worldShader.uniform[WU_texture], 0);
-
- GLfloat coord_back[] = {
- loc.x, loc.y + height, z + 0.1f,
- loc.x + width, loc.y + height, z + 0.1f,
- loc.x + width, loc.y + height + game::HLINE * 2, z + 0.1f,
-
- loc.x + width, loc.y + height + game::HLINE * 2, z + 0.1f,
- loc.x, loc.y + height + game::HLINE * 2, z + 0.1f,
- loc.x, loc.y + height, z + 0.1f,
- };
-
- GLfloat coord_front[] = {
- loc.x, loc.y + height, z,
- loc.x + health / maxHealth * width, loc.y + height, z,
- loc.x + health / maxHealth * width, loc.y + height + game::HLINE * 2, z,
-
- loc.x + health / maxHealth * width, loc.y + height + game::HLINE * 2, z,
- loc.x, loc.y + height + game::HLINE * 2, z,
- loc.x, loc.y + height, z,
- };
-
- glBindTexture(GL_TEXTURE_2D, backH);
- GLfloat tex[] = { 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
-
- 1.0, 1.0,
- 0.0, 1.0,
- 0.0, 0.0,
- };
- glVertexAttribPointer(Render::worldShader.coord, 3, GL_FLOAT, GL_FALSE, 0, coord_back);
- glVertexAttribPointer(Render::worldShader.tex, 2, GL_FLOAT, GL_FALSE, 0, tex);
- glDrawArrays(GL_TRIANGLES, 0, 6);
-
- glBindTexture(GL_TEXTURE_2D, frontH);
- glVertexAttribPointer(Render::worldShader.coord, 3, GL_FLOAT, GL_FALSE, 0, coord_front);
- glVertexAttribPointer(Render::worldShader.tex, 2, GL_FLOAT, GL_FALSE, 0, tex);
- glDrawArrays(GL_TRIANGLES, 0, 6);
-}
-
-Render::worldShader.disable();
-Render::worldShader.unuse();
-}
-
-/**
- * Handles NPC movement, usually just random walking.
- */
-
-void NPC::
-wander(int timeRun)
-{
- static int direction;
-
- if (forcedMove)
- return;
-
- if (hitCooldown)
- hitCooldown--;
-
- if (targetx != 0.9112001f) {
- if (loc.x > targetx + HLINES(5))
- vel.x = HLINES(-0.018);
- else if (loc.x < targetx - HLINES(5))
- vel.x = HLINES(0.018);
- else {
- targetx = 0.9112001f;
- vel.x = 0;
- }
- } else if (ticksToUse == 0) {
- ticksToUse = timeRun;
-
- vel.x = HLINES(0.008);
- direction = (randGet() % 3 - 1);
-
- if (direction == 0)
- ticksToUse *= 2;
-
- vel.x *= direction;
- }
-
- if (vel.x < 0)
- currentWorld->goWorldLeft(this);
-
- ticksToUse--;
-}
-
-void NPC::addAIFunc(bool preload)
-{
- if (preload)
- aipreload.push_back(this);
- else
- ++dialogCount;
-}
-
-extern int commonAIFunc(NPC *speaker);
-
-void NPC::interact() { //have the npc's interact back to the player
- std::thread([this]{
- std::vector<XMLElement *> dopt;
- XMLDocument *xml;
- XMLElement *exml,*oxml;
-
- static unsigned int oldidx = 9999;
- const char *ptr;
- std::string nname;
- unsigned int idx;
- bool stop;
- float tgt = 0.12345678f;
- bool pmove = true, advance = false;
-
- loc.y += 5;
-
- // freeze the npc, face the player
- canMove = false;
- left = (player->loc.x < loc.x);
- right = !left;
-
- // if there's actual scripted stuff to do, do it
- if (dialogCount && dialogIndex != 9999) {
- // load the XML file and find the dialog tags
- if (outnabout == 0) {
- xml = ¤tXMLDoc;
- } else if (outnabout < 0) {
- xml = new XMLDocument();
- xml->LoadFile((xmlFolder + currentWorld->getToLeft()).c_str());
- } else {
- xml = new XMLDocument();
- xml->LoadFile((xmlFolder + currentWorld->getToRight()).c_str());
- }
-
-COMMONAIFUNC:
- idx = 0;
- stop = false;
- exml = xml->FirstChildElement("Dialog");
-
- // search for the dialog block associated with this npc
- while (exml->StrAttribute("name") != name)
- exml = exml->NextSiblingElement();
-
- // search for the desired text block
- exml = exml->FirstChildElement();
- do {
- if (std::string("text") == exml->Name() && exml->UnsignedAttribute("id") == (unsigned)dialogIndex)
- break;
- } while ((exml = exml->NextSiblingElement()));
-
- // handle quest tags
- if ((oxml = exml->FirstChildElement("quest"))) {
- std::string qname;
-
- // iterate through all quest tags
- do {
- // assign quest
- if (!(qname = oxml->StrAttribute("assign")).empty())
- player->qh.assign(qname, oxml->StrAttribute("desc"), (oxml->GetText() == nullptr) ? "" : oxml->GetText());
-
- // check / finish quest
- else if (!(qname = oxml->StrAttribute("check")).empty()) {
- if (player->qh.hasQuest(qname) && player->qh.finish(qname)) {
- // QuestHandler::finish() did all the work..
- break;
- } else {
- // run error dialog
- oldidx = dialogIndex;
- dialogIndex = oxml->UnsignedAttribute("fail");
- goto COMMONAIFUNC;
- }
- }
- } while((oxml = oxml->NextSiblingElement("quest")));
- }
-
- // handle give tags
- if ((oxml = exml->FirstChildElement("give"))) {
- do player->inv->addItem(oxml->Attribute("id"), oxml->UnsignedAttribute("count"));
- while ((oxml = oxml->NextSiblingElement("give")));
- }
-
- // handle take tags
- if ((oxml = exml->FirstChildElement("take"))) {
- do player->inv->takeItem(oxml->Attribute("id"), oxml->UnsignedAttribute("count"));
- while ((oxml = oxml->NextSiblingElement()));
- }
-
- // handle movement directs
- if ((oxml = exml->FirstChildElement("gotox"))) {
- moveTo((tgt = std::stoi(oxml->GetText())));
- if (oxml->QueryBoolAttribute("playerMove", &pmove) != XML_NO_ERROR)
- pmove = true;
- if (oxml->QueryBoolAttribute("advance", &advance) != XML_NO_ERROR)
- advance = false;
- }
-
- // handle attribute setting
- if ((oxml = exml->FirstChildElement("set"))) {
- do game::setValue(oxml->StrAttribute("id"), oxml->StrAttribute("value"));
- while ((oxml = oxml->NextSiblingElement()));
- game::briceUpdate();
- }
-
- // asdlfkj
-
- auto txml = exml->FirstChildElement("content");
- if (txml == nullptr)
- goto OTHERSTUFF;
-
- ptr = txml->GetText() - 1;
- while (*++ptr && isspace(*ptr));
-
- // handle dialog options
- if ((oxml = exml->FirstChildElement("option"))) {
- std::string optstr;
-
- // convert option strings to a colon-separated format
- do {
- // append the next option
- optstr.append(std::string(":") + oxml->Attribute("text"));
-
- // save the associated XMLElement
- dopt.push_back(oxml);
- } while ((oxml = oxml->NextSiblingElement()));
-
- // run the dialog stuff
- ui::dialogBox(name, optstr, false, ptr);
- ui::waitForDialog();
-
- if (ui::dialogOptChosen)
- exml = dopt[ui::dialogOptChosen - 1];
-
- dopt.clear();
- }
-
- // optionless dialog
- else {
- ui::dialogBox(name, "", false, ptr);
- ui::waitForDialog();
- }
-
-OTHERSTUFF:
-
- // trigger other npcs if desired
- if (!(nname = exml->StrAttribute("call")).empty()) {
- NPC *n = dynamic_cast<NPC *>(*std::find_if(std::begin(currentWorld->entity), std::end(currentWorld->entity), [nname](Entity *e) {
- return (e->type == NPCT && e->name == nname);
- }));
-
- if (exml->QueryUnsignedAttribute("callid", &idx) == XML_NO_ERROR) {
- n->dialogIndex = idx;
- n->addAIFunc(false);
- }
- }
-
- if (tgt != 0.12345678f) {
- stop = canMove;
- canMove = true;
- while (targetx != 0.9112001f) {
- if (!pmove)
- player->speed = 0;
- }
- if (!pmove) {
- pmove = true;
- player->speed = 1;
- }
- canMove = stop;
- }
-
- // handle potential following dialogs
- if ((idx = exml->UnsignedAttribute("nextid"))) {
- dialogIndex = idx;
-
- // stop talking
- if (exml->QueryBoolAttribute("stop", &stop) == XML_NO_ERROR && stop) {
- dialogIndex = 9999;
- dialogCount--;
- }
-
- // pause, allow player to click npc to continue
- else if (exml->QueryBoolAttribute("pause", &stop) == XML_NO_ERROR && stop) {
- //return 1;
- }
-
- // instantly continue
- else {
- goto COMMONAIFUNC;
- }
- }
-
- // advance if desired
- else if (advance) {
- goto COMMONAIFUNC;
- }
-
- // stop talking
- else {
- // error text?
- if (oldidx != 9999) {
- dialogIndex = oldidx;
- oldidx = 9999;
- } else {
- dialogIndex = 9999;
- dialogCount--;
- }
- }
- } else {
- ui::dialogBox(name, "", false, randomDialog[randDialog]);
- }
-
- ui::waitForDialog();
- canMove = true;
- }).detach();
-}
-
-void Merchant::wander(int timeRun) {
- static int direction;
-
- if (forcedMove)
- return;
-
- if (ticksToUse == 0) {
- ticksToUse = timeRun;
-
- vel.x = HLINES(0.008);
- direction = (randGet() % 3 - 1);
-
- if (direction == 0)
- ticksToUse *= 2;
-
- vel.x *= direction;
- }
-
- if (vel.x < 0)
- currentWorld->goWorldLeft(this);
- if (inside != nullptr) {
- loc.y = inside->loc.y + HLINES(2);
- vel.y = GRAVITY_CONSTANT * 5;
- if (loc.x <= inside->loc.x + HLINES(5))
- loc.x = inside->loc.x + HLINES(5);
- else if (loc.x + width >= inside->loc.x + inside->width - HLINES(5))
- loc.x = inside->loc.x + inside->width - width - HLINES(5);
- }
- ticksToUse--;
-}
-
-void Merchant::interact() {
- std::thread([this]{
- ui::merchantBox(name.c_str(), trade[currTrade], ":Accept:Good-Bye", false, toSay->c_str());
- ui::waitForDialog();
-
- // handle normal dialog options
- switch (ui::dialogOptChosen) {
- // Accept
- case 1:
- if (!(player->inv->takeItem(trade[currTrade].item[1], trade[currTrade].quantity[1]))) {
- player->inv->addItem(trade[currTrade].item[0],trade[currTrade].quantity[0]);
- toSay = &text[1];
- interact();
- } else {
- toSay = &text[2];
- interact();
- }
- break;
-
- // Good-bye
- case 2:
- break;
-
- default:
- break;
- }
-
- // handle merchant-specific dialog options
- switch (ui::merchOptChosen) {
- // left arrow
- case 1:
- if (currTrade)
- currTrade--;
- ui::dontTypeOut();
- interact(); // TODO should we nest like this?
- break;
-
- // right arrow
- case 2:
- if (currTrade < trade.size() - 1)
- currTrade++;
- ui::dontTypeOut();
- interact();
- break;
-
- default:
- break;
- toSay = &text[0];
- }
- }).detach();
-}
-
-void Object::interact(void) {
- std::thread([this]{
- if(questObject && alive){
- ui::dialogBox(player->name, ":Yes:No", false, pickupDialog);
- ui::waitForDialog();
- if (ui::dialogOptChosen == 1) {
- player->inv->addItem(iname, 1);
- alive = false;
- }
- }else{
- alive = false;
- player->inv->addItem(iname, 1);
- }
- }).detach();
-}
-
-bool Entity::isInside(vec2 coord) const {
- return coord.x >= loc.x &&
- coord.x <= loc.x + width &&
- coord.y >= loc.y &&
- coord.y <= loc.y + height;
-}
-
-/*
- * This spawns the structures
- *
- * Structures::spawn This allows us to spawn buildings and large amounts of entities with it.
- * Passed are the type and x and y coordinates. These set the x and y coords
- * of the structure being spawned, the type pass just determines what rules to follow
- * when spawing the structure and entities. In theory this function can also spawn
- * void spawn points for large amounts of entities. This would allow for the spawn
- * point to have non-normal traits so it could be invisible or invincible...
-*/
-
-unsigned int Structures::spawn(BUILD_SUB sub, float x, float y) {
- loc.x = x;
- loc.y = y;
- type = STRUCTURET;
-
- alive = true;
- canMove = false;
-
- bsubtype = sub;
- dim2 dim;
-
- z = 1.0;
- /*
- * tempN is the amount of entities that will be spawned in the village. Currently the village
- * will spawn bewteen 2 and 7 villagers for the starting hut.
- */
-
- //unsigned int tempN = (randGet() % 5 + 2);
-
- if (textureLoc.empty())
- textureLoc = inWorld->getSTextureLocation(sub);
-
- switch(sub) {
- case STALL_MARKET:
- tex = TextureIterator({ textureLoc });
- dim = Texture::imageDim(textureLoc);
- width = HLINES(dim.x/2);
- height = HLINES(dim.y/2);
- break;
- default:
- tex = TextureIterator({ textureLoc });
- dim = Texture::imageDim(textureLoc);
- width = HLINES(dim.x/2);
- height = HLINES(dim.y/2);
- inv = NULL;
- break;
- }
-
- return 0;
-}
-
-/*Particles::Particles(const Structures *&s, vec2 vell, Color c, float d, )
-{
-
-}*/
-
-Particles::Particles(float x, float y, float w, float h, float vx, float vy, Color c, float d)
-{
- loc = vec2 {x, y};
- vel = vec2 {vx, vy};
- width = w;
- height = h;
- color = c;
- duration = d;
- gravity = true;
- fountain = false;
- behind = false;
- 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 * index.x, 0.125f * (8.0f - index.y));
-
- float z = (behind ? 2.0f : 0.9f) + zOffset;
-
- // lower left
- *(p++) = loc.x;
- *(p++) = loc.y;
- *(p++) = z;
-
- *(p++) = tc.x;
- *(p++) = tc.y;
-
- // lower right
- *(p++) = loc.x + width;
- *(p++) = loc.y;
- *(p++) = z;
-
- *(p++) = tc.x;
- *(p++) = tc.y;
-
- // upper right
- *(p++) = loc.x + width;
- *(p++) = loc.y + height;
- *(p++) = z;
-
- *(p++) = tc.x;
- *(p++) = tc.y;
-
- // upper right
- *(p++) = loc.x + width;
- *(p++) = loc.y + height;
- *(p++) = z;
-
- *(p++) = tc.x;
- *(p++) = tc.y;
-
- // upper left
- *(p++) = loc.x;
- *(p++) = loc.y + height;
- *(p++) = z;
-
- *(p++) = tc.x;
- *(p++) = tc.y;
-
- // lower left
- *(p++) = loc.x;
- *(p++) = loc.y;
- *(p++) = z;
-
- *(p++) = tc.x;
- *(p++) = tc.y;
-}
-
-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;
-
- // handle bounce
- if (bounce) {
- vel.y *= -0.2f;
- vel.x /= 4.0f;
- } else {
- vel = 0.0f;
- canMove = false;
- }
- }
-
- // handle gravity
- else if (gravity && vel.y > -1.0f) {
- vel.y -= _gravity * delta;
- }
-
- // handle lifetime
- duration -= delta;
-}
-
-bool Particles::timeUp(void)
-{
- return !(duration > 0);
-}
-
-void Player::save(void) {
- std::string data;
- std::ofstream out (xmlFolder + ".main.dat", std::ios::out | std::ios::binary);
- std::cout<<"Saving player data..."<<std::endl;
- data.append(std::to_string((int)loc.x) + "\n");
- data.append(std::to_string((int)loc.y) + "\n");
- data.append(std::to_string((int)health) + "\n");
- data.append(std::to_string((int)maxHealth) + "\n");
- data.append(std::to_string((int)game::time::getTickCount()) + "\n");
-
- data.append("qwer\n");
- data.append(std::to_string((int)inv->Items.size()) + "\n");
- for(auto &i : inv->Items) {
- if(i.second)
- data.append(std::to_string(uint(i.second)) + "\n" + i.first->name + "\n");
- }
- data.append("qwer\n");
-
- data.append(std::string(currentXML.data() + 4) + "\n");
-
- data.append("dOnE\0");
- out.write(data.data(),data.size());
- out.close();
-}
-
-void Player::sspawn(float x,float y) {
- unsigned int i;
- int count;
- std::ifstream in (xmlFolder + ".main.dat", std::ios::in | std::ios::binary);
- spawn(x,y);
-
- if (in.good()) {
- std::istringstream data;
- std::string ddata;
- std::streampos len;
-
- in.seekg(0,std::ios::end);
- len = in.tellg();
- in.seekg(0,std::ios::beg);
-
- std::vector<char> buf (len,'\0');
- in.read(buf.data(),buf.size());
-
- data.rdbuf()->pubsetbuf(buf.data(),buf.size());
-
- std::getline(data,ddata);
- loc.x = std::stoi(ddata);
- std::getline(data,ddata);
- loc.y = std::stoi(ddata);
- std::getline(data,ddata);
- health = std::stoi(ddata);
- std::getline(data,ddata);
- maxHealth = std::stoi(ddata);
- std::getline(data,ddata);
- game::time::tick(std::stoi(ddata));
-
- std::getline(data,ddata);
- std::getline(data,ddata);
-
- for (i = std::stoi(ddata);i;i--) {
- std::getline(data,ddata);
- if (ddata == "qwer")
- break;
- count = std::stoi(ddata);
-
- std::getline(data,ddata);
- if (ddata == "qwer")
- break;
- inv->addItem(ddata, (uint)count);
- }
-
- std::getline(data,ddata);
- currentWorld = loadWorldFromXMLNoSave(ddata);
-
- in.close();
- }
-}
--- /dev/null
+#include <entities.hpp>
+
+#include <istream>
+#include <sstream>
+#include <fstream>
+
+#include <ui.hpp>
+#include <world.hpp>
+#include <gametime.hpp>
+#include <brice.hpp>
+
+#include <render.hpp>
+#include <engine.hpp>
+
+///NEW
+#include <components.hpp>
+#include <entityx/entityx.h>
+///OLD
+
+extern std::istream *names;
+
+extern Player *player; // main.cpp
+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;
+
+// the size of the player's inventory
+const unsigned int PLAYER_INV_SIZE = 43;
+// the size of an NPC's inventory
+const unsigned int NPC_INV_SIZE = 3;
+
+static std::vector<std::string> randomDialog (readFileA("assets/dialog_en-us"));
+
+
+void PlayerSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt)
+{
+ (void)en;
+ (void)ev;
+ (void)dt;
+
+ if (!m_MoveLeft && !m_MoveRight)
+ (*m_Player)->vel.x = 0;
+}
+
+void PlayerSystem::configure(entityx::EventManager &ev)
+{
+ ev.subscribe<KeyDownEvent>(*this);
+ ev.subscribe<KeyUpEvent>(*this);
+}
+
+extern World *currentWorldToLeft;
+extern World *currentWorldToRight;
+extern bool gameRunning;
+extern bool inBattle;
+
+void PlayerSystem::receive(const KeyUpEvent &kue)
+{
+ auto p = *m_Player;
+ auto kc = kue.keycode;
+
+ if (kc == SDLK_ESCAPE) {
+ ui::menu::toggle();
+ p->save();
+ } else if (kc == getControl(1)) {
+ m_MoveLeft = false;
+ } else if (kc == getControl(2)) {
+ m_MoveRight = false;
+ } else if (kc == getControl(3) || kc == getControl(4)) {
+ player->speed = 1;
+ } else if (kc == getControl(5)) {
+ if (p->inv->invHover) {
+ p->inv->invHover = false;
+ } else {
+ if (!p->inv->selected)
+ p->inv->invOpening ^= true;
+ else
+ p->inv->selected = false;
+
+ p->inv->mouseSel = false;
+ }
+
+ // disable action ui
+ ui::action::disable();
+ }
+}
+
+void PlayerSystem::receive(const KeyDownEvent &kde)
+{
+ auto p = *m_Player;
+ auto kc = kde.keycode;
+
+ auto worldSwitch = [&](const WorldSwitchInfo& wsi){
+ player->canMove = false;
+ ui::toggleBlackFast();
+ ui::waitForCover();
+ game::events.emit<BGMToggleEvent>(wsi.first->bgm, wsi.first);
+ std::tie(currentWorld, player->loc) = wsi; // using p causes segfault
+ game::engine.getSystem<WorldSystem>()->setWorld(currentWorld);
+ ui::toggleBlackFast();
+ ui::waitForUncover();
+ player->canMove = true; // using p causes segfault
+ };
+
+ if ((kc == SDLK_SPACE) && (game::canJump & p->ground)) {
+ p->loc.y += HLINES(2);
+ p->vel.y = .4;
+ p->ground = false;
+ }
+
+ if (!ui::dialogBoxExists || ui::dialogPassive) {
+ if (kc == getControl(0)) {
+ if (inBattle) {
+ std::thread([&](void){
+ auto thing = dynamic_cast<Arena *>(currentWorld)->exitArena(p);
+ if (thing.first != currentWorld)
+ worldSwitch(thing);
+ }).detach();
+ } else if (!ui::fadeIntensity) {
+ std::thread([&](void){
+ auto thing = currentWorld->goInsideStructure(p);
+ if (thing.first != currentWorld)
+ worldSwitch(thing);
+ }).detach();
+ }
+ } else if (kc == getControl(1)) {
+ if (!ui::fadeEnable) {
+ p->vel.x = -PLAYER_SPEED_CONSTANT;
+ if (std::stoi(game::getValue("Slow")) == 1)
+ p->vel.x /= 2.0f;
+ p->left = m_MoveLeft = true;
+ p->right = m_MoveRight = false;
+ if (currentWorldToLeft) {
+ std::thread([&](void){
+ auto thing = currentWorld->goWorldLeft(p);
+ if (thing.first != currentWorld)
+ worldSwitch(thing);
+ }).detach();
+ }
+ }
+ } else if (kc == getControl(2)) {
+ if (!ui::fadeEnable) {
+ p->vel.x = PLAYER_SPEED_CONSTANT;
+ if (std::stoi(game::getValue("Slow")) == 1)
+ p->vel.x /= 2.0f;
+ p->right = m_MoveRight = true;
+ p->left = m_MoveLeft = false;
+ if (currentWorldToRight) {
+ std::thread([&](void){
+ auto thing = currentWorld->goWorldRight(p);
+ if (thing.first != currentWorld)
+ worldSwitch(thing);
+ }).detach();
+ }
+ }
+ } else if (kc == getControl(3)) {
+ if (game::canSprint)
+ p->speed = 2.0f;
+ } else if (kc == getControl(4)) {
+ p->speed = .5;
+ } else if (kc == getControl(5)) {
+ /*static int heyOhLetsGo = 0;
+
+ //edown = true;
+
+ // start hover counter?
+ if (!heyOhLetsGo) {
+ heyOhLetsGo = game::time::getTickCount();
+ p->inv->mouseSel = false;
+ }
+
+ // run hover thing
+ if (game::time::getTickCount() - heyOhLetsGo >= 2 && !(p->inv->invOpen) && !(p->inv->selected)) {
+ p->inv->invHover = true;
+
+ // enable action ui
+ ui::action::enable();
+ }*/
+ }
+ } else if (kc == SDLK_DELETE) {
+ game::endGame();
+ } else if (kc == SDLK_t) {
+ game::time::tick(50);
+ }
+}
+
+
+void getRandomName(Entity *e)
+{
+ auto names = readFileA("assets/names_en-us");
+ auto name = names[randGet() % names.size()];
+
+ // gender is a binary construct
+ e->gender = (name[0] == 'm') ? MALE : FEMALE;
+
+ e->name = &name[1];
+}
+
+Entity::Entity(void)
+{
+ vel = 0;
+ width = 0;
+ height = 0;
+ health = 0;
+ maxHealth = 0;
+ outnabout = 0;
+ targetx = 0.9112001f;
+
+ type = UNKNOWNT;
+
+ // set flags
+ alive = true;
+ right = true;
+ left = false;
+ near = false;
+ canMove = true;
+ ground = false;
+ forcedMove = false;
+ z = 0.0f;
+
+ // clear counters
+ ticksToUse = 0;
+ hitCooldown = 0;
+
+ hitDuration = maxHitDuration = 0;
+
+ inv = nullptr;
+}
+
+// spawns the entity you pass to it based off of coords and global entity settings
+void Entity::spawn(float x, float y)
+{
+ loc.x = x;
+ loc.y = y;
+
+ if (health == 0 && maxHealth == 0)
+ health = maxHealth = 1;
+
+ // generate a name
+ if (type == MOBT)
+ name = "mob";
+ else
+ getRandomName(this);
+
+ setCooldown(0);
+}
+
+void Entity::takeHit(unsigned int _health, unsigned int cooldown)
+{
+ if (hitCooldown <= 1) {
+ // modify variables
+ health = fmax(health - _health, 0);
+ forcedMove = true;
+ hitCooldown = cooldown;
+
+ hitDuration = maxHitDuration = 350.0f;
+
+ // pushback
+ vel.x = player->left ? -0.5f : 0.5f;
+ vel.y = 0.2f;
+ }
+}
+
+unsigned int Entity::coolDown()
+{
+ return hitCooldown;
+}
+
+void Entity::setCooldown(unsigned int c)
+{
+ hitCooldown = c;
+}
+
+void Entity::handleHits(void)
+{
+ hitCooldown = fmax(static_cast<int>(hitCooldown - game::time::getDeltaTime()), 0);
+ hitDuration = fmax(hitDuration - game::time::getDeltaTime(), 0);
+
+ if (!forcedMove)
+ return;
+
+ // reduce knockback
+ if ((vel.x > 0.0005f) || (vel.x < -0.0005f))
+ vel.x *= 0.6f;
+ else
+ forcedMove = false;
+}
+
+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
+{
+ return alive;
+}
+
+bool Entity::isHit(void) const
+{
+ return forcedMove;
+}
+
+void Entity::moveTo(float dest_x)
+{
+ targetx = dest_x;
+}
+
+Player::Player() : Entity()
+{
+ width = HLINES(10);
+ height = HLINES(16);
+
+ type = PLAYERT; //set type to player
+ subtype = 0;
+ health = maxHealth = 100;
+ speed = 1;
+ canMove = true;
+
+ tex = TextureIterator({"assets/player/playerk.png",
+ "assets/player/playerk1.png",
+ "assets/player/playerk2.png",
+ "assets/player/playerk3.png",
+ "assets/player/playerk4.png",
+ "assets/player/playerk5.png",
+ "assets/player/playerk6.png",
+ "assets/player/playerk7.png",
+ "assets/player/playerk8.png"
+ });
+
+ inv = new Inventory(PLAYER_INV_SIZE);
+ dim2 tmpDim = Texture::imageDim(tex.getTexturePath(0));
+ width = HLINES(tmpDim.x/2);
+ height = HLINES(tmpDim.y/2);
+
+ z = -2.0;
+}
+
+Player::~Player()
+{
+ delete inv;
+ delete &tex;
+}
+
+void Player::createFromXML(XMLElement *e, World *w=nullptr)
+{
+ (void)e;
+ (void)w;
+}
+
+void Player::saveToXML(void)
+{}
+
+NPC::NPC() : Entity()
+{
+ width = HLINES(10);
+ height = HLINES(16);
+
+ type = NPCT; //sets type to npc
+ subtype = 0;
+
+ health = maxHealth = 100;
+
+ maxHealth = health = 100;
+ canMove = true;
+
+ tex = TextureIterator({"assets/NPC.png"});
+ inv = new Inventory(NPC_INV_SIZE);
+
+ randDialog = randGet() % randomDialog.size();
+ dialogIndex = 0;
+ dialogCount = 0;
+
+ dim2 tmpDim = Texture::imageDim(tex.getTexturePath(0));
+ width = HLINES(tmpDim.x/2);
+ height = HLINES(tmpDim.y/2);
+}
+
+NPC::~NPC()
+{
+ delete inv;
+}
+
+void NPC::createFromXML(XMLElement *e, World *w=nullptr)
+{
+ std::string npcname;
+ bool dialog;
+ unsigned int flooor;
+
+ xmle = e;
+ (void)w;
+
+ // spawn at coordinates if desired
+ E_LOAD_COORDS(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;
+
+ // custom health value
+ E_LOAD_HEALTH;
+
+ // movemenet
+ if (e->QueryBoolAttribute("canMove", &dialog) == XML_NO_ERROR)
+ canMove = dialog;
+
+ // dialog index
+ if (e->QueryUnsignedAttribute("dindex", &flooor) == XML_NO_ERROR)
+ dialogIndex = flooor;
+}
+
+void NPC::saveToXML(void)
+{
+ E_SAVE_HEALTH;
+ E_SAVE_COORDS;
+ xmle->SetAttribute("dindex", dialogIndex);
+}
+
+Merchant::Merchant() : NPC()
+{
+ width = HLINES(10);
+ height = HLINES(16);
+
+ type = MERCHT; //sets type to merchant
+ subtype = 0;
+
+ health = maxHealth = 100;
+
+ canMove = true;
+
+ trade.reserve(100);
+ currTrade = 0;
+
+ inside = nullptr;
+
+ //tex = new Texturec(1,"assets/NPC.png");
+ //inv = new Inventory(NPC_INV_SIZE);
+ //inv = new Inventory(1);
+
+ //randDialog = rand() % RAND_DIALOG_COUNT - 1;
+ dialogIndex = 0;
+
+ dim2 tmpDim = Texture::imageDim(tex.getTexturePath(0));
+ width = HLINES(tmpDim.x/2);
+ height = HLINES(tmpDim.y/2);
+}
+
+Merchant::~Merchant()
+{
+}
+
+void Merchant::saveToXML(void){}
+
+Structures::Structures() : Entity()
+{
+ type = STRUCTURET;
+ canMove = false;
+ health = maxHealth = 1;
+}
+
+Structures::~Structures()
+{
+}
+
+extern std::string currentXMLRaw;
+
+void Structures::createFromXML(XMLElement *e, World *w)
+{
+ float spawnx;
+
+ if (e->QueryBoolAttribute("alive", &alive) == XML_NO_ERROR && !alive) {
+ //die();
+ return;
+ }
+
+ inWorld = w;
+ inside = e->StrAttribute("inside");
+
+ // edge
+ if (!inside.empty()) {
+ insideWorld = loadWorldFromXMLNoTakeover(inside);
+ }
+
+ textureLoc = e->StrAttribute("texture");
+
+ insideTex = Texture::loadTexture(e->StrAttribute("insideTexture"));
+
+ spawn(static_cast<BUILD_SUB>(e->UnsignedAttribute("type")),
+ e->QueryFloatAttribute("spawnx", &spawnx) == XML_NO_ERROR ? spawnx : (randGet() % w->getTheWidth() / 2.0f),
+ 100);
+
+ xmle = e;
+}
+
+void Structures::saveToXML(void)
+{
+ xmle->SetAttribute("alive", alive);
+}
+
+Object::Object()
+{
+ type = OBJECTT;
+}
+
+Object::Object(std::string in, std::string pd)
+{
+ iname = in;
+
+ pickupDialog = pd;
+ questObject = !pd.empty();
+
+ type = OBJECTT;
+ width = getItemWidth(in);
+ height = getItemHeight(in);
+
+ tex = TextureIterator({getItemTexturePath(in)});
+}
+
+Object::~Object()
+{
+}
+
+void Object::createFromXML(XMLElement *e, World *w=nullptr)
+{
+ (void)e;
+ (void)w;
+}
+
+void Object::saveToXML(void)
+{}
+
+void Object::reloadTexture(void)
+{
+ tex = TextureIterator({getItemTexturePath(iname)});
+ width = getItemWidth(iname);
+ height = getItemHeight(iname);
+}
+
+bool Entity::isNear(const Entity *e) {
+ return (e != nullptr) ? (pow(e->loc.x - loc.x, 2) + pow(e->loc.y - loc.y, 2) <= pow(HLINES(40), 2)) : false;
+}
+
+void NPC::drawThingy(void) const
+{
+ if (dialogCount) {
+ const auto w = width / 3;
+ GLfloat tex_coord[] = {
+ 0, 0, 1, 0, 1, 1,
+ 1, 1, 0, 1, 0, 0
+ };
+ const GLfloat c[4] = {
+ loc.x + w, loc.y + height, loc.x + w * 2, loc.y + height + w
+ };
+ GLfloat coords[] = {
+ c[0], c[1], z, c[2], c[1], z, c[2], c[3], z,
+ c[2], c[3], z, c[0], c[3], z, c[0], c[1], z
+ };
+
+ // TODO use texture made for this
+ static GLuint thingyColor = Texture::genColor(Color(236, 238, 15));
+
+ Render::worldShader.use();
+ Render::worldShader.enable();
+
+ glBindTexture(GL_TEXTURE_2D, thingyColor);
+
+ glVertexAttribPointer(Render::worldShader.coord, 3, GL_FLOAT, GL_FALSE, 0, coords);
+ glVertexAttribPointer(Render::worldShader.tex, 2, GL_FLOAT, GL_FALSE, 0, tex_coord);
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+
+ Render::worldShader.disable();
+ Render::worldShader.unuse();
+ }
+}
+
+void Entity::draw(void)
+{
+ GLfloat tex_coord[] = {0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+
+ 1.0, 1.0,
+ 0.0, 1.0,
+ 0.0, 0.0};
+
+ GLfloat tex_coordL[] = {1.0, 0.0,
+ 0.0, 0.0,
+ 0.0, 1.0,
+
+ 0.0, 1.0,
+ 1.0, 1.0,
+ 1.0, 0.0};
+
+ GLfloat coords[] = {loc.x, loc.y, z,
+ loc.x + width, loc.y, z,
+ loc.x + width, loc.y + height, z,
+
+ loc.x + width, loc.y + height, z,
+ loc.x, loc.y + height, z,
+ loc.x, loc.y, z};
+
+
+ glActiveTexture(GL_TEXTURE0);
+
+ if (!alive)
+ return;
+
+ if (type == NPCT) {
+ NPCp(this)->drawThingy();
+
+ if (gender == MALE)
+ glColor3ub(255, 255, 255);
+ else if (gender == FEMALE)
+ glColor3ub(255, 105, 180);
+ } else if (type == MOBT) {
+ if (Mobp(this)->rider != nullptr) {
+ Mobp(this)->rider->loc.x = loc.x + width * 0.25f;
+ Mobp(this)->rider->loc.y = loc.y + height - HLINES(5);
+ Mobp(this)->rider->vel.y = .12;
+ Mobp(this)->rider->z = z + 0.01;
+ }
+ }
+ switch(type) {
+ case PLAYERT:
+ static int texState = 0;
+ if (speed && !(game::time::getTickCount() % ((2.0f/speed) < 1 ? 1 : (int)((float)2.0f/(float)speed)))) {
+ if (++texState == 9)
+ texState = 1;
+ glActiveTexture(GL_TEXTURE0);
+ tex(texState);
+ }
+ if (!ground) {
+ glActiveTexture(GL_TEXTURE0);
+ tex(0);
+ } else if (vel.x) {
+ glActiveTexture(GL_TEXTURE0);
+ tex(texState);
+ } else {
+ glActiveTexture(GL_TEXTURE0);
+ tex(0);
+ }
+ break;
+ case MOBT:
+ if (!Mobp(this)->bindTex())
+ goto NOPE;
+ break;
+ case STRUCTURET:
+ /* fall through */
+ default:
+ glActiveTexture(GL_TEXTURE0);
+ tex(0);
+ break;
+ }
+
+ Render::worldShader.use();
+ // make the entity hit flash red
+ if (maxHitDuration-hitDuration) {
+ float flashAmt = 1-(hitDuration/maxHitDuration);
+ glUniform4f(Render::worldShader.uniform[WU_tex_color], 1.0, flashAmt, flashAmt, 1.0);
+ }
+
+ glUniform1i(Render::worldShader.uniform[WU_texture], 0);
+ Render::worldShader.enable();
+
+ glVertexAttribPointer(Render::worldShader.coord, 3, GL_FLOAT, GL_FALSE, 0, coords);
+ if (left)
+ glVertexAttribPointer(Render::worldShader.tex, 2, GL_FLOAT, GL_FALSE, 0 ,tex_coordL);
+ else
+ glVertexAttribPointer(Render::worldShader.tex, 2, GL_FLOAT, GL_FALSE, 0 ,tex_coord);
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+
+ glUniform4f(Render::worldShader.uniform[WU_tex_color], 1.0, 1.0, 1.0, 1.0);
+NOPE:
+if (near && type != MOBT)
+ ui::putStringCentered(loc.x+width/2,loc.y-ui::fontSize-game::HLINE/2,name);
+if (health != maxHealth) {
+
+ static GLuint frontH = Texture::genColor(Color(255,0,0));
+ static GLuint backH = Texture::genColor(Color(150,0,0));
+ glUniform1i(Render::worldShader.uniform[WU_texture], 0);
+
+ GLfloat coord_back[] = {
+ loc.x, loc.y + height, z + 0.1f,
+ loc.x + width, loc.y + height, z + 0.1f,
+ loc.x + width, loc.y + height + game::HLINE * 2, z + 0.1f,
+
+ loc.x + width, loc.y + height + game::HLINE * 2, z + 0.1f,
+ loc.x, loc.y + height + game::HLINE * 2, z + 0.1f,
+ loc.x, loc.y + height, z + 0.1f,
+ };
+
+ GLfloat coord_front[] = {
+ loc.x, loc.y + height, z,
+ loc.x + health / maxHealth * width, loc.y + height, z,
+ loc.x + health / maxHealth * width, loc.y + height + game::HLINE * 2, z,
+
+ loc.x + health / maxHealth * width, loc.y + height + game::HLINE * 2, z,
+ loc.x, loc.y + height + game::HLINE * 2, z,
+ loc.x, loc.y + height, z,
+ };
+
+ glBindTexture(GL_TEXTURE_2D, backH);
+ GLfloat tex[] = { 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+
+ 1.0, 1.0,
+ 0.0, 1.0,
+ 0.0, 0.0,
+ };
+ glVertexAttribPointer(Render::worldShader.coord, 3, GL_FLOAT, GL_FALSE, 0, coord_back);
+ glVertexAttribPointer(Render::worldShader.tex, 2, GL_FLOAT, GL_FALSE, 0, tex);
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+
+ glBindTexture(GL_TEXTURE_2D, frontH);
+ glVertexAttribPointer(Render::worldShader.coord, 3, GL_FLOAT, GL_FALSE, 0, coord_front);
+ glVertexAttribPointer(Render::worldShader.tex, 2, GL_FLOAT, GL_FALSE, 0, tex);
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+}
+
+Render::worldShader.disable();
+Render::worldShader.unuse();
+}
+
+/**
+ * Handles NPC movement, usually just random walking.
+ */
+
+void NPC::
+wander(int timeRun)
+{
+ static int direction;
+
+ if (forcedMove)
+ return;
+
+ if (hitCooldown)
+ hitCooldown--;
+
+ if (targetx != 0.9112001f) {
+ if (loc.x > targetx + HLINES(5))
+ vel.x = HLINES(-0.018);
+ else if (loc.x < targetx - HLINES(5))
+ vel.x = HLINES(0.018);
+ else {
+ targetx = 0.9112001f;
+ vel.x = 0;
+ }
+ } else if (ticksToUse == 0) {
+ ticksToUse = timeRun;
+
+ vel.x = HLINES(0.008);
+ direction = (randGet() % 3 - 1);
+
+ if (direction == 0)
+ ticksToUse *= 2;
+
+ vel.x *= direction;
+ }
+
+ if (vel.x < 0)
+ currentWorld->goWorldLeft(this);
+
+ ticksToUse--;
+}
+
+void NPC::addAIFunc(bool preload)
+{
+ if (preload)
+ aipreload.push_back(this);
+ else
+ ++dialogCount;
+}
+
+extern int commonAIFunc(NPC *speaker);
+
+void NPC::interact() { //have the npc's interact back to the player
+ std::thread([this]{
+ std::vector<XMLElement *> dopt;
+ XMLDocument *xml;
+ XMLElement *exml,*oxml;
+
+ static unsigned int oldidx = 9999;
+ const char *ptr;
+ std::string nname;
+ unsigned int idx;
+ bool stop;
+ float tgt = 0.12345678f;
+ bool pmove = true, advance = false;
+
+ loc.y += 5;
+
+ // freeze the npc, face the player
+ canMove = false;
+ left = (player->loc.x < loc.x);
+ right = !left;
+
+ // if there's actual scripted stuff to do, do it
+ if (dialogCount && dialogIndex != 9999) {
+ // load the XML file and find the dialog tags
+ if (outnabout == 0) {
+ xml = ¤tXMLDoc;
+ } else if (outnabout < 0) {
+ xml = new XMLDocument();
+ xml->LoadFile((xmlFolder + currentWorld->getToLeft()).c_str());
+ } else {
+ xml = new XMLDocument();
+ xml->LoadFile((xmlFolder + currentWorld->getToRight()).c_str());
+ }
+
+COMMONAIFUNC:
+ idx = 0;
+ stop = false;
+ exml = xml->FirstChildElement("Dialog");
+
+ // search for the dialog block associated with this npc
+ while (exml->StrAttribute("name") != name)
+ exml = exml->NextSiblingElement();
+
+ // search for the desired text block
+ exml = exml->FirstChildElement();
+ do {
+ if (std::string("text") == exml->Name() && exml->UnsignedAttribute("id") == (unsigned)dialogIndex)
+ break;
+ } while ((exml = exml->NextSiblingElement()));
+
+ // handle quest tags
+ if ((oxml = exml->FirstChildElement("quest"))) {
+ std::string qname;
+
+ // iterate through all quest tags
+ do {
+ // assign quest
+ if (!(qname = oxml->StrAttribute("assign")).empty())
+ player->qh.assign(qname, oxml->StrAttribute("desc"), (oxml->GetText() == nullptr) ? "" : oxml->GetText());
+
+ // check / finish quest
+ else if (!(qname = oxml->StrAttribute("check")).empty()) {
+ if (player->qh.hasQuest(qname) && player->qh.finish(qname)) {
+ // QuestHandler::finish() did all the work..
+ break;
+ } else {
+ // run error dialog
+ oldidx = dialogIndex;
+ dialogIndex = oxml->UnsignedAttribute("fail");
+ goto COMMONAIFUNC;
+ }
+ }
+ } while((oxml = oxml->NextSiblingElement("quest")));
+ }
+
+ // handle give tags
+ if ((oxml = exml->FirstChildElement("give"))) {
+ do player->inv->addItem(oxml->Attribute("id"), oxml->UnsignedAttribute("count"));
+ while ((oxml = oxml->NextSiblingElement("give")));
+ }
+
+ // handle take tags
+ if ((oxml = exml->FirstChildElement("take"))) {
+ do player->inv->takeItem(oxml->Attribute("id"), oxml->UnsignedAttribute("count"));
+ while ((oxml = oxml->NextSiblingElement()));
+ }
+
+ // handle movement directs
+ if ((oxml = exml->FirstChildElement("gotox"))) {
+ moveTo((tgt = std::stoi(oxml->GetText())));
+ if (oxml->QueryBoolAttribute("playerMove", &pmove) != XML_NO_ERROR)
+ pmove = true;
+ if (oxml->QueryBoolAttribute("advance", &advance) != XML_NO_ERROR)
+ advance = false;
+ }
+
+ // handle attribute setting
+ if ((oxml = exml->FirstChildElement("set"))) {
+ do game::setValue(oxml->StrAttribute("id"), oxml->StrAttribute("value"));
+ while ((oxml = oxml->NextSiblingElement()));
+ game::briceUpdate();
+ }
+
+ // asdlfkj
+
+ auto txml = exml->FirstChildElement("content");
+ if (txml == nullptr)
+ goto OTHERSTUFF;
+
+ ptr = txml->GetText() - 1;
+ while (*++ptr && isspace(*ptr));
+
+ // handle dialog options
+ if ((oxml = exml->FirstChildElement("option"))) {
+ std::string optstr;
+
+ // convert option strings to a colon-separated format
+ do {
+ // append the next option
+ optstr.append(std::string(":") + oxml->Attribute("text"));
+
+ // save the associated XMLElement
+ dopt.push_back(oxml);
+ } while ((oxml = oxml->NextSiblingElement()));
+
+ // run the dialog stuff
+ ui::dialogBox(name, optstr, false, ptr);
+ ui::waitForDialog();
+
+ if (ui::dialogOptChosen)
+ exml = dopt[ui::dialogOptChosen - 1];
+
+ dopt.clear();
+ }
+
+ // optionless dialog
+ else {
+ ui::dialogBox(name, "", false, ptr);
+ ui::waitForDialog();
+ }
+
+OTHERSTUFF:
+
+ // trigger other npcs if desired
+ if (!(nname = exml->StrAttribute("call")).empty()) {
+ NPC *n = dynamic_cast<NPC *>(*std::find_if(std::begin(currentWorld->entity), std::end(currentWorld->entity), [nname](Entity *e) {
+ return (e->type == NPCT && e->name == nname);
+ }));
+
+ if (exml->QueryUnsignedAttribute("callid", &idx) == XML_NO_ERROR) {
+ n->dialogIndex = idx;
+ n->addAIFunc(false);
+ }
+ }
+
+ if (tgt != 0.12345678f) {
+ stop = canMove;
+ canMove = true;
+ while (targetx != 0.9112001f) {
+ if (!pmove)
+ player->speed = 0;
+ }
+ if (!pmove) {
+ pmove = true;
+ player->speed = 1;
+ }
+ canMove = stop;
+ }
+
+ // handle potential following dialogs
+ if ((idx = exml->UnsignedAttribute("nextid"))) {
+ dialogIndex = idx;
+
+ // stop talking
+ if (exml->QueryBoolAttribute("stop", &stop) == XML_NO_ERROR && stop) {
+ dialogIndex = 9999;
+ dialogCount--;
+ }
+
+ // pause, allow player to click npc to continue
+ else if (exml->QueryBoolAttribute("pause", &stop) == XML_NO_ERROR && stop) {
+ //return 1;
+ }
+
+ // instantly continue
+ else {
+ goto COMMONAIFUNC;
+ }
+ }
+
+ // advance if desired
+ else if (advance) {
+ goto COMMONAIFUNC;
+ }
+
+ // stop talking
+ else {
+ // error text?
+ if (oldidx != 9999) {
+ dialogIndex = oldidx;
+ oldidx = 9999;
+ } else {
+ dialogIndex = 9999;
+ dialogCount--;
+ }
+ }
+ } else {
+ ui::dialogBox(name, "", false, randomDialog[randDialog]);
+ }
+
+ ui::waitForDialog();
+ canMove = true;
+ }).detach();
+}
+
+void Merchant::wander(int timeRun) {
+ static int direction;
+
+ if (forcedMove)
+ return;
+
+ if (ticksToUse == 0) {
+ ticksToUse = timeRun;
+
+ vel.x = HLINES(0.008);
+ direction = (randGet() % 3 - 1);
+
+ if (direction == 0)
+ ticksToUse *= 2;
+
+ vel.x *= direction;
+ }
+
+ if (vel.x < 0)
+ currentWorld->goWorldLeft(this);
+ if (inside != nullptr) {
+ loc.y = inside->loc.y + HLINES(2);
+ vel.y = GRAVITY_CONSTANT * 5;
+ if (loc.x <= inside->loc.x + HLINES(5))
+ loc.x = inside->loc.x + HLINES(5);
+ else if (loc.x + width >= inside->loc.x + inside->width - HLINES(5))
+ loc.x = inside->loc.x + inside->width - width - HLINES(5);
+ }
+ ticksToUse--;
+}
+
+void Merchant::interact() {
+ std::thread([this]{
+ ui::merchantBox(name.c_str(), trade[currTrade], ":Accept:Good-Bye", false, toSay->c_str());
+ ui::waitForDialog();
+
+ // handle normal dialog options
+ switch (ui::dialogOptChosen) {
+ // Accept
+ case 1:
+ if (!(player->inv->takeItem(trade[currTrade].item[1], trade[currTrade].quantity[1]))) {
+ player->inv->addItem(trade[currTrade].item[0],trade[currTrade].quantity[0]);
+ toSay = &text[1];
+ interact();
+ } else {
+ toSay = &text[2];
+ interact();
+ }
+ break;
+
+ // Good-bye
+ case 2:
+ break;
+
+ default:
+ break;
+ }
+
+ // handle merchant-specific dialog options
+ switch (ui::merchOptChosen) {
+ // left arrow
+ case 1:
+ if (currTrade)
+ currTrade--;
+ ui::dontTypeOut();
+ interact(); // TODO should we nest like this?
+ break;
+
+ // right arrow
+ case 2:
+ if (currTrade < trade.size() - 1)
+ currTrade++;
+ ui::dontTypeOut();
+ interact();
+ break;
+
+ default:
+ break;
+ toSay = &text[0];
+ }
+ }).detach();
+}
+
+void Object::interact(void) {
+ std::thread([this]{
+ if(questObject && alive){
+ ui::dialogBox(player->name, ":Yes:No", false, pickupDialog);
+ ui::waitForDialog();
+ if (ui::dialogOptChosen == 1) {
+ player->inv->addItem(iname, 1);
+ alive = false;
+ }
+ }else{
+ alive = false;
+ player->inv->addItem(iname, 1);
+ }
+ }).detach();
+}
+
+bool Entity::isInside(vec2 coord) const {
+ return coord.x >= loc.x &&
+ coord.x <= loc.x + width &&
+ coord.y >= loc.y &&
+ coord.y <= loc.y + height;
+}
+
+/*
+ * This spawns the structures
+ *
+ * Structures::spawn This allows us to spawn buildings and large amounts of entities with it.
+ * Passed are the type and x and y coordinates. These set the x and y coords
+ * of the structure being spawned, the type pass just determines what rules to follow
+ * when spawing the structure and entities. In theory this function can also spawn
+ * void spawn points for large amounts of entities. This would allow for the spawn
+ * point to have non-normal traits so it could be invisible or invincible...
+*/
+
+unsigned int Structures::spawn(BUILD_SUB sub, float x, float y) {
+ loc.x = x;
+ loc.y = y;
+ type = STRUCTURET;
+
+ alive = true;
+ canMove = false;
+
+ bsubtype = sub;
+ dim2 dim;
+
+ z = 1.0;
+ /*
+ * tempN is the amount of entities that will be spawned in the village. Currently the village
+ * will spawn bewteen 2 and 7 villagers for the starting hut.
+ */
+
+ //unsigned int tempN = (randGet() % 5 + 2);
+
+ if (textureLoc.empty())
+ textureLoc = inWorld->getSTextureLocation(sub);
+
+ switch(sub) {
+ case STALL_MARKET:
+ tex = TextureIterator({ textureLoc });
+ dim = Texture::imageDim(textureLoc);
+ width = HLINES(dim.x/2);
+ height = HLINES(dim.y/2);
+ break;
+ default:
+ tex = TextureIterator({ textureLoc });
+ dim = Texture::imageDim(textureLoc);
+ width = HLINES(dim.x/2);
+ height = HLINES(dim.y/2);
+ inv = NULL;
+ break;
+ }
+
+ return 0;
+}
+
+/*Particles::Particles(const Structures *&s, vec2 vell, Color c, float d, )
+{
+
+}*/
+
+Particles::Particles(float x, float y, float w, float h, float vx, float vy, Color c, float d)
+{
+ loc = vec2 {x, y};
+ vel = vec2 {vx, vy};
+ width = w;
+ height = h;
+ color = c;
+ duration = d;
+ gravity = true;
+ fountain = false;
+ behind = false;
+ 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 * index.x, 0.125f * (8.0f - index.y));
+
+ float z = (behind ? 2.0f : 0.9f) + zOffset;
+
+ // lower left
+ *(p++) = loc.x;
+ *(p++) = loc.y;
+ *(p++) = z;
+
+ *(p++) = tc.x;
+ *(p++) = tc.y;
+
+ // lower right
+ *(p++) = loc.x + width;
+ *(p++) = loc.y;
+ *(p++) = z;
+
+ *(p++) = tc.x;
+ *(p++) = tc.y;
+
+ // upper right
+ *(p++) = loc.x + width;
+ *(p++) = loc.y + height;
+ *(p++) = z;
+
+ *(p++) = tc.x;
+ *(p++) = tc.y;
+
+ // upper right
+ *(p++) = loc.x + width;
+ *(p++) = loc.y + height;
+ *(p++) = z;
+
+ *(p++) = tc.x;
+ *(p++) = tc.y;
+
+ // upper left
+ *(p++) = loc.x;
+ *(p++) = loc.y + height;
+ *(p++) = z;
+
+ *(p++) = tc.x;
+ *(p++) = tc.y;
+
+ // lower left
+ *(p++) = loc.x;
+ *(p++) = loc.y;
+ *(p++) = z;
+
+ *(p++) = tc.x;
+ *(p++) = tc.y;
+}
+
+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;
+
+ // handle bounce
+ if (bounce) {
+ vel.y *= -0.2f;
+ vel.x /= 4.0f;
+ } else {
+ vel = 0.0f;
+ canMove = false;
+ }
+ }
+
+ // handle gravity
+ else if (gravity && vel.y > -1.0f) {
+ vel.y -= _gravity * delta;
+ }
+
+ // handle lifetime
+ duration -= delta;
+}
+
+bool Particles::timeUp(void)
+{
+ return !(duration > 0);
+}
+
+void Player::save(void) {
+ std::string data;
+ std::ofstream out (xmlFolder + ".main.dat", std::ios::out | std::ios::binary);
+ std::cout<<"Saving player data..."<<std::endl;
+ data.append(std::to_string((int)loc.x) + "\n");
+ data.append(std::to_string((int)loc.y) + "\n");
+ data.append(std::to_string((int)health) + "\n");
+ data.append(std::to_string((int)maxHealth) + "\n");
+ data.append(std::to_string((int)game::time::getTickCount()) + "\n");
+
+ data.append("qwer\n");
+ data.append(std::to_string((int)inv->Items.size()) + "\n");
+ for(auto &i : inv->Items) {
+ if(i.second)
+ data.append(std::to_string(uint(i.second)) + "\n" + i.first->name + "\n");
+ }
+ data.append("qwer\n");
+
+ data.append(std::string(currentXML.data() + 4) + "\n");
+
+ data.append("dOnE\0");
+ out.write(data.data(),data.size());
+ out.close();
+}
+
+void Player::sspawn(float x,float y) {
+ unsigned int i;
+ int count;
+ std::ifstream in (xmlFolder + ".main.dat", std::ios::in | std::ios::binary);
+ spawn(x,y);
+
+ if (in.good()) {
+ std::istringstream data;
+ std::string ddata;
+ std::streampos len;
+
+ in.seekg(0,std::ios::end);
+ len = in.tellg();
+ in.seekg(0,std::ios::beg);
+
+ std::vector<char> buf (len,'\0');
+ in.read(buf.data(),buf.size());
+
+ data.rdbuf()->pubsetbuf(buf.data(),buf.size());
+
+ std::getline(data,ddata);
+ loc.x = std::stoi(ddata);
+ std::getline(data,ddata);
+ loc.y = std::stoi(ddata);
+ std::getline(data,ddata);
+ health = std::stoi(ddata);
+ std::getline(data,ddata);
+ maxHealth = std::stoi(ddata);
+ std::getline(data,ddata);
+ game::time::tick(std::stoi(ddata));
+
+ std::getline(data,ddata);
+ std::getline(data,ddata);
+
+ for (i = std::stoi(ddata);i;i--) {
+ std::getline(data,ddata);
+ if (ddata == "qwer")
+ break;
+ count = std::stoi(ddata);
+
+ std::getline(data,ddata);
+ if (ddata == "qwer")
+ break;
+ inv->addItem(ddata, (uint)count);
+ }
+
+ std::getline(data,ddata);
+ currentWorld = loadWorldFromXMLNoSave(ddata);
+
+ in.close();
+ }
+}
+++ /dev/null
-#include <inventory.hpp>
-
-#include <numeric>
-
-#include <entities.hpp>
-#include <gametime.hpp>
-
-#include <render.hpp>
-
-#include <tinyxml2.h>
-using namespace tinyxml2;
-
-extern Player *player;
-extern GLuint invUI;
-static vec2 itemLoc;
-static const unsigned char numSlot = 7;
-Mix_Chunk* swordSwing;
-
-static std::vector<NewCurrency *> currencyMap;
-static std::vector<Item *> ItemMap;
-
-
-void itemDraw(Player *p, Item* d);
-
-bool strCaseCmp(std::string one, std::string two)
-{
- for (auto &s : one) {
- s = std::tolower(s);
- }
- for (auto &t : two) {
- t = std::tolower(t);
- }
-
- if (one == two) return true;
- return false;
-}
-
-void items(void)
-{
- XMLDocument xml;
- xml.LoadFile("config/items.xml");
- XMLElement *exml = xml.FirstChildElement("item");
- XMLElement *cxml = xml.FirstChildElement("currency");
-
- while (cxml) {
-
- // NEWEWEWEWEWEWEWEW
- // TODO
-
-
- cxml = cxml->NextSiblingElement();
- }
- while (exml) {
-
- std::string name = exml->Attribute("type");
- // if the type is blank
- if (strCaseCmp(name, "blank")) {
-
- ItemMap.push_back(new BaseItem());
-
- // if the type is a sword
- } else if (strCaseCmp(name, "sword")) {
-
- Sword *tmpSword = new Sword();
- tmpSword->setDamage(exml->FloatAttribute("damage"));
- ItemMap.push_back(tmpSword->clone());
- delete tmpSword;
-
- // if the type is a bow
- } else if (strCaseCmp(name, "bow")) {
-
- Bow *tmpBow = new Bow();
- tmpBow->setDamage(exml->FloatAttribute("damage"));
- ItemMap.push_back(tmpBow->clone());
- delete tmpBow;
-
- // arrow
- } else if (strCaseCmp(name, "arrow")) {
-
- Arrow *tmpArrow = new Arrow();
- tmpArrow->setDamage(exml->FloatAttribute("damage"));
- ItemMap.push_back(tmpArrow->clone());
- delete tmpArrow;
-
- // uncooked / raw food
- }else if (strCaseCmp(name, "raw food")) {
-
- ItemMap.push_back(new RawFood());
-
- // cooked food or natural food
- } else if (strCaseCmp(name, "food") || strCaseCmp(name, "cooked food")) {
-
- ItemMap.push_back(new Food());
-
- // light
- } else if (strCaseCmp(name, "light")) {
-
- ItemMap.push_back(new ItemLight());
-
- // if type was not specified make it a base item
- } else {
-
- ItemMap.push_back(new BaseItem());
- }
-
- // set how much of the item we can stack
- if(exml->QueryUnsignedAttribute("maxStackSize", &ItemMap.back()->maxStackSize) != XML_NO_ERROR) {
- ItemMap.back()->maxStackSize = 1;
- }
-
- // set all of the texture frames we can use
- ItemMap.back()->tex = new Texturec(1, exml->Attribute("sprite"));
-
- // get the width and height of the object based off of its sprite
- dim2 tmpDim = Texture::imageDim(exml->Attribute("sprite"));
- ItemMap.back()->dim.x = HLINES(tmpDim.x/2);
- ItemMap.back()->dim.y = HLINES(tmpDim.y/2);
-
- ItemMap.back()->name = exml->Attribute("name");
-
- exml = exml->NextSiblingElement();
- }
-}
-
-int Inventory::addItem(std::string name, uint count)
-{
- for (uint i = 0; i < ItemMap.size(); i++) {
- if (strCaseCmp(ItemMap[i]->name, name)) {
- for (auto &it : Items) {
- if (it.second && strCaseCmp(it.first->name, name)) {
- if ((it.second + count) < it.first->maxStackSize) {
- it.second += count;
- return 0;
- } else {
- count -= (it.second + count) - it.first->maxStackSize;
- it.second = it.first->maxStackSize;
- }
- }
- }
- uint tmpCount = count;
- do {
- if ((count) > ItemMap[i]->maxStackSize) {
- count -= ItemMap[i]->maxStackSize;
- tmpCount = ItemMap[i]->maxStackSize;
- } else {
- tmpCount = count;
- count = 0;
- }
- Items[os] = std::make_pair(ItemMap[i]->clone(), tmpCount);
- if (!Items[os+1].second) {
- os++;
- } else {
- for (uint z = 0; z < Items.size(); z++) {
- if (!Items[z].second) {
- os = z;
- }
- }
- }
- } while (count > 0);
- return 0;
- }
- }
- return -1;
-}
-
-int Inventory::takeItem(std::string name, uint count)
-{
-
- // returns
- // 0 = good
- // -1 = no such item exists
- // -2 = if item doesnt exist in inventory
- // postive items = number returned is how many more the item needs
-
- std::string iden;
-
- for (uint i = 0; i < ItemMap.size(); i++) {
- if (ItemMap[i]->name == name) {
- iden = name;
- break;
- }
- }
-
- if (iden.empty()) {
- return -1;
- }
-
- for (auto &i : Items) {
- if (i.second && i.first->name == iden) {
- if (count > i.second) {
- return (count - i.second);
- } else {
- i.second -= count;
-
- }
- return 0;
- }
- }
-
- return -2;
-}
-
-int Inventory::hasItem(std::string name) {
-
- for (auto &i : Items) {
- if (i.first->name == name) {
- return i.second;
- }
- }
-
- return 0;
-}
-void initInventorySprites(void) {
-
- items();
-
- // keep
- swordSwing = Mix_LoadWAV("assets/sounds/shortSwing.wav");
- Mix_Volume(2,100);
-}
-
-void destroyInventory(void) {
-
- // NEWEWEWEWEWEWEWEW
- while (!ItemMap.empty()) {
- delete ItemMap.back();
- ItemMap.pop_back();
- }
-
- Mix_FreeChunk(swordSwing);
-}
-
-
-const char *getItemTexturePath(std::string name){
- for (auto &i : ItemMap) {
- if (i->name == name)
- return i->tex->texLoc[0].c_str();
- }
- return NULL;
-}
-
-GLuint getItemTexture(std::string name) {
- for (auto &i : ItemMap) {
- if (i->name == name) {
- return i->tex->image[0];
- }
- }
- return 0;
-}
-
-float getItemWidth(std::string name) {
- for (auto &i : ItemMap) {
- if (i->name == name)
- return i->dim.x;
- }
- return 0;
-}
-
-float getItemHeight(std::string name) {
- for (auto &i : ItemMap) {
- if (i->name == name)
- return i->dim.y;
- }
- return 0;
-}
-
-Inventory::Inventory(unsigned int s) {
- sel=0;
- size=s;
-
- Items.resize(size);
- for (auto &i : Items) {
- i = std::make_pair(nullptr, 0);
- }
-}
-
-Inventory::~Inventory(void) {
-}
-
-void Inventory::setSelection(unsigned int s) {
- sel=s;
-}
-
-void Inventory::setSelectionUp() {
- if (!sel--)
- sel++;
-}
-
-void Inventory::setSelectionDown() {
- if (++sel >= numSlot)
- sel = numSlot - 1;
-}
-
-void Inventory::draw(void) {
- static std::vector<int>dfp(numSlot);
- static std::vector<Ray>iray(numSlot);
- static std::vector<vec2>curCoord(numSlot);
- static int range = 200;
-
- static std::vector<int>curdfp(4);
- static std::vector<Ray>curRay(4);
- static std::vector<vec2>curCurCoord(4);
- static int curRange = 100;
-
- static std::vector<int>massDfp(32);
- static std::vector<vec2>massRay(32);
- static std::vector<int>massOrder = {9,10,11,12,13,14,22,21,20,19,18,17,16,8,0,1,2,3,4,5,6,7,15,23,31,30,29,28,27,26,25,24};
- static std::vector<int>massOrderClosing = {31,30,23,29,22,15,28,21,14,7,27,20,13,6,26,19,12,5,25,18,11,4,24,17,10,3,16,9,2,8,1,0};
- static int massRange = 200;
-
- static int itemWide = 45;
- float angleB = (float)180/(float)numSlot;
- float angle = float(angleB/2.0f);
- unsigned int a = 0;
- //static vec2 mouseStart = {0,0};
-
- auto deltaTime = game::time::getDeltaTime();
- auto SCREEN_WIDTH = game::SCREEN_WIDTH;
- auto SCREEN_HEIGHT = game::SCREEN_HEIGHT;
-
- for (auto &r : iray) {
- r.start.x = player->loc.x + (player->width / 2);
- r.start.y = player->loc.y + (player->height / 2);
- curCoord[a++] = r.start;
- } a = 0;
-
- for (auto &cr : curRay) {
- cr.start.x = (offset.x + SCREEN_WIDTH / 2);
- cr.start.y = offset.y - (a * itemWide * 1.5f);
- curCurCoord[a++] = cr.start;
- } a = 0;
-
- for (int r = 0; r < 4; r++) {
- for (int c = 0; c < 8; c++) {
- massRay[a ].x = ((offset.x - SCREEN_WIDTH / 2) + itemWide) + c * itemWide * 1.5f;
- massRay[a++].y = ((offset.y + SCREEN_HEIGHT / 2) - itemWide * 1.5f) - r * itemWide * 1.5f;
- }
- } a = 0;
-
- auto averagef = [](const std::vector<int> &v) {
- auto sum = std::accumulate(std::begin(v), std::end(v), 0);
- return sum / v.size();
- };
-
- ui::fontTransInv = std::clamp(255 * (averagef(dfp) / range), 0ul, 255ul);
-
- if (invOpening) {
- for (auto &d : dfp) {
- if (!a || dfp[a - 1] > 50)
- d += 4.0f * deltaTime;
- if (d > range)
- d = range;
- a++;
- } a = 0;
-
- for (auto &cd : curdfp) {
- if (!a || curdfp[a - 1] > 90)
- cd += 3.0f * deltaTime;
- if (cd > curRange)
- cd = curRange;
- a++;
- } a = 0;
-
- while (a < massOrder.size()) {
- if (!a || massDfp[massOrder[a - 1]] > massRange * 0.75f)
- massDfp[massOrder[a]] += 20.0f * deltaTime;
- if (massDfp[massOrder[a]] > massRange)
- massDfp[massOrder[a]] = massRange;
- a++;
- } a = 0;
-
- if (numSlot > 0)
- invOpen = true;
- } else {
- for (auto &d : dfp) {
- if (d > 0)
- d -= 4.5f * deltaTime;
- }
- for (auto &cd : curdfp) {
- if (cd > 0)
- cd -= 3.0f * deltaTime;
- }
-
- while (a < massRay.size()) {
- if (!a || massDfp[massOrderClosing[a - 1]] <= 0)
- massDfp[massOrderClosing[a]] -= 30.0f * deltaTime;
- else if (massDfp[massOrderClosing[a - 1]] < 0)
- massDfp[massOrderClosing[a - 1]] = 0;
- a++;
- } a = 0;
-
- if (std::all_of(std::begin(massDfp), std::end(massDfp), [](auto d) { return d <= 0; })) {
- invOpen = false;
- for (auto &md : massDfp) {
- if (md < 0)
- md = 0;
- }
- }
-
- }
-
- /*
- * a = 0
- */
-
- if (invOpen) {
- Render::useShader(&Render::textShader);
- for(auto &mr : massRay) {
- float t = (((float)massDfp[a]/(float)massRange)*.5f);
- glActiveTexture(GL_TEXTURE0);
- Render::textShader.use();
-
- glBindTexture(GL_TEXTURE_2D, Texture::genColor(Color(0.0f,0.0f,0.0f, t >= 0? 255*t : 0)));
- glUniform1i(Render::textShader.uniform[WU_texture], 0);
-
- Render::drawRect(vec2(mr.x-(itemWide/2), mr.y-(itemWide/2)), vec2(mr.x-(itemWide/2)+itemWide, mr.y-(itemWide/2)+itemWide), -6.0);
-
- glUseProgram(0);
- if (!Items.empty() && a+numSlot < Items.size() && Items[a+numSlot].second) {
- Render::textShader.use();
- glBindTexture(GL_TEXTURE_2D, Items[a+numSlot].first->tex->image[0]);//itemtex[items[a+numSlot].id]);
- glUniform4f(Render::textShader.uniform[WU_tex_color], 1.0f, 1.0f, 1.0f, ((float)massDfp[a]/(float)(massRange?massRange:1))*0.8f);
-
- if (Items[a+numSlot].first->dim.y > Items[a+numSlot].first->dim.x) {
- Render::drawRect(vec2(mr.x-((itemWide/2)*((float)Items[a+numSlot].first->dim.x/(float)Items[a+numSlot].first->dim.y)), mr.y-(itemWide/2)),
- vec2(mr.x+((itemWide/2)*((float)Items[a+numSlot].first->dim.x/(float)Items[a+numSlot].first->dim.y)), mr.y+(itemWide/2)), -6.1);
- } else {
- Render::drawRect(vec2(mr.x-(itemWide/2),mr.y-(itemWide/2)*((float)Items[a+numSlot].first->dim.y/(float)Items[a+numSlot].first->dim.x)),
- vec2(mr.x-(itemWide/2),mr.y+(itemWide/2)*((float)Items[a+numSlot].first->dim.y/(float)Items[a+numSlot].first->dim.x)), -6.1);
- }
- ui::setFontColor(255,255,255,((float)massDfp[a]/(float)(massRange?massRange:1))*255);
- ui::putText(mr.x-(itemWide/2)+(itemWide*.85),mr.y-(itemWide/2),"%d",Items[a+numSlot].second);
- ui::setFontColor(255,255,255,255);
- Render::textShader.unuse();
- }
- a++;
- }a=0;
-
- for(auto &cr : curRay) {
- curCurCoord[a].x -= float((curdfp[a]) * cos(-1));
- curCurCoord[a].y += float((curdfp[a]) * sin(0));
- cr.end = curCurCoord[a];
-
- float curTrans = (((float)curdfp[a]/(float)(curRange?curRange:1))*0.5f);
-
- Render::textShader.use();
- glBindTexture(GL_TEXTURE_2D, Texture::genColor(Color(0.0f, 0.0f, 0.0f, curTrans >= 0 ? 255 * curTrans : 0)));
- Render::drawRect(vec2(cr.end.x-(itemWide/2), cr.end.y-(itemWide/2)),
- vec2(cr.end.x-(itemWide/2)+itemWide,cr.end.y-(itemWide/2)+itemWide), -6.0);
- Render::textShader.unuse();
- a++;
- }a=0;
-
- for(auto &r : iray) {
- angle = 180 - (angleB * a) - angleB / 2.0f;
- curCoord[a].x += float((dfp[a]) * cos(angle*PI/180));
- curCoord[a].y += float((dfp[a]) * sin(angle*PI/180));
- r.end = curCoord[a];
-
- float t = ((float)dfp[a]/(float)(range?range:1))*0.5f;
-
- Render::textShader.use();
- glBindTexture(GL_TEXTURE_2D, Texture::genColor(Color(0.0f, 0.0f, 0.0f, t >= 0 ? 255 * t : 0)));
- Render::drawRect(vec2(r.end.x-(itemWide/2), r.end.y-(itemWide/2)),
- vec2(r.end.x-(itemWide/2)+itemWide,r.end.y-(itemWide/2)+itemWide), -6.0);
-
- if (!Items.empty() && a < numSlot && Items[a].second) {
- glBindTexture(GL_TEXTURE_2D, Items[a].first->tex->image[0]);//itemtex[items[a].id]);
- glUniform4f(Render::textShader.uniform[WU_tex_color], 1.0f, 1.0f, 1.0f, ((float)dfp[a]/(float)(range?range:1))*0.8f);
- if (Items[a].first->dim.y > Items[a].first->dim.x) {
- Render::drawRect(vec2(r.end.x-((itemWide/2)*((float)Items[a].first->dim.x/(float)Items[a].first->dim.y)), r.end.y-(itemWide/2)),
- vec2(r.end.x+((itemWide/2)*((float)Items[a].first->dim.x/(float)Items[a].first->dim.y)), r.end.y+(itemWide/2)), -6.1);
- } else {
- Render::drawRect(vec2(r.end.x-(itemWide/2),r.end.y-(itemWide/2)*((float)Items[a].first->dim.y/(float)Items[a].first->dim.x)),
- vec2(r.end.x+(itemWide/2),r.end.y+(itemWide/2)*((float)Items[a].first->dim.y/(float)Items[a].first->dim.x)), -6.1);
- }
- ui::setFontColor(255,255,255,((float)dfp[a]/(float)(range?range:1))*255);
- ui::putStringCentered(r.end.x,r.end.y-(itemWide*.9),Items[a].first->name);//itemMap[items[a].id]->name);
- ui::putText(r.end.x-(itemWide/2)+(itemWide*.85),r.end.y-(itemWide/2),"%d",Items[a].second);
- ui::setFontColor(255,255,255,255);
- }
- Render::textShader.unuse();
- if (sel == a) {
- static float sc = 1;
- static bool up;
- up ? sc += .0025*deltaTime : sc -= .0025*deltaTime;
- if (sc > 1.2) {
- up = false;
- sc = 1.2;
- }
- if (sc < 1.0) {
- up = true;
- sc = 1.0;
- }
- float t = ((float)dfp[a]/(float)(range?range:1));
- Render::useShader(&Render::textShader);
-
- Render::textShader.use();
- glUniform4f(Render::textShader.uniform[WU_tex_color], 1.0, 1.0, 1.0, 1.0);
-
- // bottom
- glBindTexture(GL_TEXTURE_2D, Texture::genColor(Color(255, 255, 255, t >= 0 ? 255 * t : 0)));
- Render::drawRect(vec2(r.end.x - (itemWide*sc)/2 - (itemWide*sc)*.09,r.end.y - (itemWide*sc)/2 - (itemWide*sc)*.09),
- vec2(r.end.x + (itemWide*sc)/2 + (itemWide*sc)*.09,r.end.y - (itemWide*sc)/2), -6.2);
-
- // top
- glBindTexture(GL_TEXTURE_2D, Texture::genColor(Color(255, 255, 255, t >= 0 ? 255 * t : 0)));
- Render::drawRect(vec2(r.end.x - (itemWide*sc)/2 - (itemWide*sc)*.09,r.end.y + (itemWide*sc)/2 + (itemWide*sc)*.09),
- vec2(r.end.x + (itemWide*sc)/2 + (itemWide*sc)*.09,r.end.y + (itemWide*sc)/2), -6.2);
-
- // left
- glBindTexture(GL_TEXTURE_2D, Texture::genColor(Color(255, 255, 255, t >= 0 ? 255 * t : 0)));
- Render::drawRect(vec2(r.end.x - (itemWide*sc)/2 - (itemWide*sc)*.09,r.end.y - (itemWide*sc)/2 - (itemWide*sc)*.09),
- vec2(r.end.x - (itemWide*sc)/2 ,r.end.y + (itemWide*sc)/2 + (itemWide*sc)*.09), -6.2);
-
- // right
- glBindTexture(GL_TEXTURE_2D, Texture::genColor(Color(255, 255, 255, t >= 0 ? 255 * t : 0)));
- Render::drawRect(vec2(r.end.x + (itemWide*sc)/2 ,r.end.y - (itemWide*sc)/2 - (itemWide*sc)*.09),
- vec2(r.end.x + (itemWide*sc)/2 + (itemWide*sc)*.09,r.end.y + (itemWide*sc)/2 + (itemWide*sc)*.09), -6.2);
-
- //glUseProgram(0);
- }
- a++;
- }
- } /*else if (invHover) {
- static unsigned int highlight = 0;
- static unsigned int thing = 0;
-
- if (!mouseSel) {
- // setup?
- mouseStart.x = ui::mouse.x - offset.x;
- highlight = sel;
- thing = sel;
- mouseSel = true;
- } else {
- if((ui::mouse.x - offset.x) >= mouseStart.x){
- thing = (ui::mouse.x - offset.x - mouseStart.x)/80;
- highlight=sel+thing;
- if(highlight>numSlot-1)highlight=numSlot-1;
- if(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_LEFT)){
- sel = highlight;
- mouseSel=false;
- invHover=false;
- selected = true;
- }
- }
- if ((ui::mouse.x - offset.x) < mouseStart.x) {
- thing = (mouseStart.x - (ui::mouse.x - offset.x))/80;
- if ((int)sel - (int)thing < 0)
- highlight = 0;
- else
- highlight = sel - thing;
- if(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_LEFT)){
- sel = highlight;
- mouseSel=false;
- invHover=false;
- selected = true;
- }
- }
- }
-
- a = 0;
- for (auto &r : iray) {
- angle = 180 - (angleB * a) - angleB / 2.0f;
- curCoord[a].x += float(range) * cos(angle*PI/180);
- curCoord[a].y += float(range) * sin(angle*PI/180);
- r.end = curCoord[a];
-
- // square drawing
- glColor4f(0.0f, 0.0f, 0.0f, a == highlight ? 0.5f : 0.1f);
- glBegin(GL_QUADS);
- glVertex2i(r.end.x-(itemWide/2), r.end.y-(itemWide/2));
- glVertex2i(r.end.x+(itemWide/2), r.end.y-(itemWide/2));
- glVertex2i(r.end.x+(itemWide/2), r.end.y+(itemWide/2));
- glVertex2i(r.end.x-(itemWide/2), r.end.y+(itemWide/2));
- glEnd();
-
- if (a < items.size() && items[a].count) {
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, itemtex[items[a].id]);
- glColor4f(1.0f, 1.0f, 1.0f, a == highlight ? 0.8f : 0.2f);
- glBegin(GL_QUADS);
- if(itemMap[items[a].id]->height > itemMap[items[a].id]->width){
- glTexCoord2i(0,1);glVertex2i(r.end.x-((itemWide/2)*((float)itemMap[items[a].id]->width/(float)itemMap[items[a].id]->height)),r.end.y-(itemWide/2));
- glTexCoord2i(1,1);glVertex2i(r.end.x+((itemWide/2)*((float)itemMap[items[a].id]->width/(float)itemMap[items[a].id]->height)),r.end.y-(itemWide/2));
- glTexCoord2i(1,0);glVertex2i(r.end.x+((itemWide/2)*((float)itemMap[items[a].id]->width/(float)itemMap[items[a].id]->height)),r.end.y+(itemWide/2));
- glTexCoord2i(0,0);glVertex2i(r.end.x-((itemWide/2)*((float)itemMap[items[a].id]->width/(float)itemMap[items[a].id]->height)),r.end.y+(itemWide/2));
- }else{
- glTexCoord2i(0,1);glVertex2i(r.end.x-(itemWide/2),r.end.y-(itemWide/2)*((float)itemMap[items[a].id]->height/(float)itemMap[items[a].id]->width));
- glTexCoord2i(1,1);glVertex2i(r.end.x+(itemWide/2),r.end.y-(itemWide/2)*((float)itemMap[items[a].id]->height/(float)itemMap[items[a].id]->width));
- glTexCoord2i(1,0);glVertex2i(r.end.x+(itemWide/2),r.end.y+(itemWide/2)*((float)itemMap[items[a].id]->height/(float)itemMap[items[a].id]->width));
- glTexCoord2i(0,0);glVertex2i(r.end.x-(itemWide/2),r.end.y+(itemWide/2)*((float)itemMap[items[a].id]->height/(float)itemMap[items[a].id]->width));
- }
- glEnd();
- glDisable(GL_TEXTURE_2D);
- }
- a++;
- }
-
- if (highlight < items.size()) {
- ui::putStringCentered(player->loc.x + player->width / 2,
- player->loc.y + range * 0.75f,
- itemMap[items[highlight].id]->name
- );
- }
- }*/
- /*if (!items.empty() && items.size() > sel && items[sel].count)
- itemDraw(player,items[sel].id);*/
- if (!Items.empty() && Items.size() > sel && Items[sel].second)
- itemDraw(player, Items[sel].first);
-}
-
-void itemDraw(Player *p, Item *d) {
-
- itemLoc.y = p->loc.y+(p->height/3);
- itemLoc.x = p->left?p->loc.x-d->dim.x/2:p->loc.x+p->width-d->dim.x/2;
-
- Render::worldShader.use();
-
- if (p->left) {
- // move to center of screen
- glm::mat4 tro = glm::translate(glm::mat4(1.0f),
- glm::vec3(itemLoc.x+d->dim.x/2, itemLoc.y, 0));
- // rotate off center
- glm::mat4 rot = glm::rotate(glm::mat4(1.0f),
- static_cast<GLfloat>((d->rotation*3.14159)/180.0f),
- glm::vec3(0.0f, 0.0f, 1.0f));
- // move back to player
- glm::mat4 trt = glm::translate(glm::mat4(1.0f),
- glm::vec3(-itemLoc.x-d->dim.x/2, -itemLoc.y, 0));
- // tell shader to translate the object using steps above
- glUniformMatrix4fv(Render::worldShader.uniform[WU_transform], 1, GL_FALSE, glm::value_ptr(tro * rot * trt));
- } else {
- // move to center of screen
- glm::mat4 tro = glm::translate(glm::mat4(1.0f),
- glm::vec3(itemLoc.x+d->dim.x/2,itemLoc.y,0));
- // rotate off center
- glm::mat4 rot = glm::rotate(glm::mat4(1.0f),
- static_cast<GLfloat>((d->rotation*3.14159)/180.0f),
- glm::vec3(0.0f, 0.0f, 1.0f));
- // move back to player
- glm::mat4 trt = glm::translate(glm::mat4(1.0f),
- glm::vec3(-itemLoc.x-d->dim.x/2,-itemLoc.y,0));
- // tell shader to translate the object using steps above
- glUniformMatrix4fv(Render::worldShader.uniform[WU_transform], 1, GL_FALSE, glm::value_ptr(tro * rot * trt));
- }
-
- GLfloat itemTex[12] = {0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
-
- 1.0, 1.0,
- 0.0, 1.0,
- 0.0, 0.0};
- if (!p->left) {
- itemTex[0] = 1.0;
- itemTex[2] = 0.0;
- itemTex[4] = 0.0;
- itemTex[6] = 0.0;
- itemTex[8] = 1.0;
- itemTex[10] = 1.0;
- }
-
- GLfloat itemCoords[] = {itemLoc.x, itemLoc.y, p->z,
- itemLoc.x+d->dim.x, itemLoc.y, p->z,
- itemLoc.x+d->dim.x, itemLoc.y+d->dim.y, p->z,
-
- itemLoc.x+d->dim.x, itemLoc.y+d->dim.y, p->z,
- itemLoc.x, itemLoc.y+d->dim.y, p->z,
- itemLoc.x, itemLoc.y, p->z};
-
- glBindTexture(GL_TEXTURE_2D,d->tex->image[0]);
-
- Render::worldShader.enable();
-
- glVertexAttribPointer(Render::worldShader.coord, 3, GL_FLOAT, GL_FALSE, 0, itemCoords);
- glVertexAttribPointer(Render::worldShader.tex, 2, GL_FLOAT, GL_FALSE, 0, itemTex);
- glDrawArrays(GL_TRIANGLES, 0, 6);
-
- Render::worldShader.disable();
- Render::worldShader.unuse();
-}
-
-/*
- * This function is used to trigger the player's item's ability.
- */
-int Inventory::useItem(void)
-{
- return 0;
-}
-
-int Inventory::useCurrent()
-{
- if (Items[sel].second)
- return Items[sel].first->useItem();
- return -1;
-}
-
-void Inventory::currentAddInteract(Entity* e)
-{
- if (Items[sel].second)
- Items[sel].first->addInteract(e);
-}
-
-void Inventory::currentAddInteract(std::vector<Entity*> e)
-{
- if (Items[sel].second)
- Items[sel].first->addInteract(e);
-}
-
-bool Inventory::detectCollision(vec2 one, vec2 two) {
- (void)one;
- (void)two;
- return false;
-}
-
-const Item* Inventory::getCurrentItem(void)
-{
- if (Items.size() > 0)
- return Items[sel].first;
- else
- return nullptr;
-}
-
-void InventorySystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt)
-{
- (void)en;
- (void)ev;
- (void)dt;
-}
-
-void InventorySystem::configure(entityx::EventManager &em)
-{
- em.subscribe<MouseScrollEvent>(*this);
-}
-
-void InventorySystem::receive(const MouseScrollEvent &mse)
-{
- static int mouseWheelUpCount = 0, mouseWheelDownCount = 0;
-
- if ((mse.scrollDistance < 0) && ((++mouseWheelUpCount % 5) == 0) ) {
- mouseWheelUpCount = 0;
- player->inv->setSelectionUp();
- } else if ( (++mouseWheelDownCount % 5) == 0 ) {
- mouseWheelDownCount = 0;
- player->inv->setSelectionDown();
- }
-}
--- /dev/null
+#include <inventory.hpp>
+
+#include <numeric>
+
+#include <gametime.hpp>
+
+#include <render.hpp>
+
+#include <tinyxml2.h>
+using namespace tinyxml2;
+
+extern Player *player;
+extern GLuint invUI;
+static vec2 itemLoc;
+static const unsigned char numSlot = 7;
+Mix_Chunk* swordSwing;
+
+static std::vector<NewCurrency *> currencyMap;
+static std::vector<Item *> ItemMap;
+
+
+void itemDraw(Player *p, Item* d);
+
+bool strCaseCmp(std::string one, std::string two)
+{
+ for (auto &s : one) {
+ s = std::tolower(s);
+ }
+ for (auto &t : two) {
+ t = std::tolower(t);
+ }
+
+ if (one == two) return true;
+ return false;
+}
+
+void items(void)
+{
+ XMLDocument xml;
+ xml.LoadFile("config/items.xml");
+ XMLElement *exml = xml.FirstChildElement("item");
+ XMLElement *cxml = xml.FirstChildElement("currency");
+
+ while (cxml) {
+
+ // NEWEWEWEWEWEWEWEW
+ // TODO
+
+
+ cxml = cxml->NextSiblingElement();
+ }
+ while (exml) {
+
+ std::string name = exml->Attribute("type");
+ // if the type is blank
+ if (strCaseCmp(name, "blank")) {
+
+ ItemMap.push_back(new BaseItem());
+
+ // if the type is a sword
+ } else if (strCaseCmp(name, "sword")) {
+
+ Sword *tmpSword = new Sword();
+ tmpSword->setDamage(exml->FloatAttribute("damage"));
+ ItemMap.push_back(tmpSword->clone());
+ delete tmpSword;
+
+ // if the type is a bow
+ } else if (strCaseCmp(name, "bow")) {
+
+ Bow *tmpBow = new Bow();
+ tmpBow->setDamage(exml->FloatAttribute("damage"));
+ ItemMap.push_back(tmpBow->clone());
+ delete tmpBow;
+
+ // arrow
+ } else if (strCaseCmp(name, "arrow")) {
+
+ Arrow *tmpArrow = new Arrow();
+ tmpArrow->setDamage(exml->FloatAttribute("damage"));
+ ItemMap.push_back(tmpArrow->clone());
+ delete tmpArrow;
+
+ // uncooked / raw food
+ }else if (strCaseCmp(name, "raw food")) {
+
+ ItemMap.push_back(new RawFood());
+
+ // cooked food or natural food
+ } else if (strCaseCmp(name, "food") || strCaseCmp(name, "cooked food")) {
+
+ ItemMap.push_back(new Food());
+
+ // light
+ } else if (strCaseCmp(name, "light")) {
+
+ ItemMap.push_back(new ItemLight());
+
+ // if type was not specified make it a base item
+ } else {
+
+ ItemMap.push_back(new BaseItem());
+ }
+
+ // set how much of the item we can stack
+ if(exml->QueryUnsignedAttribute("maxStackSize", &ItemMap.back()->maxStackSize) != XML_NO_ERROR) {
+ ItemMap.back()->maxStackSize = 1;
+ }
+
+ // set all of the texture frames we can use
+ ItemMap.back()->tex = new Texturec(1, exml->Attribute("sprite"));
+
+ // get the width and height of the object based off of its sprite
+ dim2 tmpDim = Texture::imageDim(exml->Attribute("sprite"));
+ ItemMap.back()->dim.x = HLINES(tmpDim.x/2);
+ ItemMap.back()->dim.y = HLINES(tmpDim.y/2);
+
+ ItemMap.back()->name = exml->Attribute("name");
+
+ exml = exml->NextSiblingElement();
+ }
+}
+
+int Inventory::addItem(std::string name, uint count)
+{
+ for (uint i = 0; i < ItemMap.size(); i++) {
+ if (strCaseCmp(ItemMap[i]->name, name)) {
+ for (auto &it : Items) {
+ if (it.second && strCaseCmp(it.first->name, name)) {
+ if ((it.second + count) < it.first->maxStackSize) {
+ it.second += count;
+ return 0;
+ } else {
+ count -= (it.second + count) - it.first->maxStackSize;
+ it.second = it.first->maxStackSize;
+ }
+ }
+ }
+ uint tmpCount = count;
+ do {
+ if ((count) > ItemMap[i]->maxStackSize) {
+ count -= ItemMap[i]->maxStackSize;
+ tmpCount = ItemMap[i]->maxStackSize;
+ } else {
+ tmpCount = count;
+ count = 0;
+ }
+ Items[os] = std::make_pair(ItemMap[i]->clone(), tmpCount);
+ if (!Items[os+1].second) {
+ os++;
+ } else {
+ for (uint z = 0; z < Items.size(); z++) {
+ if (!Items[z].second) {
+ os = z;
+ }
+ }
+ }
+ } while (count > 0);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+int Inventory::takeItem(std::string name, uint count)
+{
+
+ // returns
+ // 0 = good
+ // -1 = no such item exists
+ // -2 = if item doesnt exist in inventory
+ // postive items = number returned is how many more the item needs
+
+ std::string iden;
+
+ for (uint i = 0; i < ItemMap.size(); i++) {
+ if (ItemMap[i]->name == name) {
+ iden = name;
+ break;
+ }
+ }
+
+ if (iden.empty()) {
+ return -1;
+ }
+
+ for (auto &i : Items) {
+ if (i.second && i.first->name == iden) {
+ if (count > i.second) {
+ return (count - i.second);
+ } else {
+ i.second -= count;
+
+ }
+ return 0;
+ }
+ }
+
+ return -2;
+}
+
+int Inventory::hasItem(std::string name) {
+
+ for (auto &i : Items) {
+ if (i.first->name == name) {
+ return i.second;
+ }
+ }
+
+ return 0;
+}
+void initInventorySprites(void) {
+
+ items();
+
+ // keep
+ swordSwing = Mix_LoadWAV("assets/sounds/shortSwing.wav");
+ Mix_Volume(2,100);
+}
+
+void destroyInventory(void) {
+
+ // NEWEWEWEWEWEWEWEW
+ while (!ItemMap.empty()) {
+ delete ItemMap.back();
+ ItemMap.pop_back();
+ }
+
+ Mix_FreeChunk(swordSwing);
+}
+
+
+const char *getItemTexturePath(std::string name){
+ for (auto &i : ItemMap) {
+ if (i->name == name)
+ return i->tex->texLoc[0].c_str();
+ }
+ return NULL;
+}
+
+GLuint getItemTexture(std::string name) {
+ for (auto &i : ItemMap) {
+ if (i->name == name) {
+ return i->tex->image[0];
+ }
+ }
+ return 0;
+}
+
+float getItemWidth(std::string name) {
+ for (auto &i : ItemMap) {
+ if (i->name == name)
+ return i->dim.x;
+ }
+ return 0;
+}
+
+float getItemHeight(std::string name) {
+ for (auto &i : ItemMap) {
+ if (i->name == name)
+ return i->dim.y;
+ }
+ return 0;
+}
+
+Inventory::Inventory(unsigned int s) {
+ sel=0;
+ size=s;
+
+ Items.resize(size);
+ for (auto &i : Items) {
+ i = std::make_pair(nullptr, 0);
+ }
+}
+
+Inventory::~Inventory(void) {
+}
+
+void Inventory::setSelection(unsigned int s) {
+ sel=s;
+}
+
+void Inventory::setSelectionUp() {
+ if (!sel--)
+ sel++;
+}
+
+void Inventory::setSelectionDown() {
+ if (++sel >= numSlot)
+ sel = numSlot - 1;
+}
+
+void Inventory::draw(void) {
+ static std::vector<int>dfp(numSlot);
+ static std::vector<Ray>iray(numSlot);
+ static std::vector<vec2>curCoord(numSlot);
+ static int range = 200;
+
+ static std::vector<int>curdfp(4);
+ static std::vector<Ray>curRay(4);
+ static std::vector<vec2>curCurCoord(4);
+ static int curRange = 100;
+
+ static std::vector<int>massDfp(32);
+ static std::vector<vec2>massRay(32);
+ static std::vector<int>massOrder = {9,10,11,12,13,14,22,21,20,19,18,17,16,8,0,1,2,3,4,5,6,7,15,23,31,30,29,28,27,26,25,24};
+ static std::vector<int>massOrderClosing = {31,30,23,29,22,15,28,21,14,7,27,20,13,6,26,19,12,5,25,18,11,4,24,17,10,3,16,9,2,8,1,0};
+ static int massRange = 200;
+
+ static int itemWide = 45;
+ float angleB = (float)180/(float)numSlot;
+ float angle = float(angleB/2.0f);
+ unsigned int a = 0;
+ //static vec2 mouseStart = {0,0};
+
+ auto deltaTime = game::time::getDeltaTime();
+ auto SCREEN_WIDTH = game::SCREEN_WIDTH;
+ auto SCREEN_HEIGHT = game::SCREEN_HEIGHT;
+
+ for (auto &r : iray) {
+ r.start.x = player->loc.x + (player->width / 2);
+ r.start.y = player->loc.y + (player->height / 2);
+ curCoord[a++] = r.start;
+ } a = 0;
+
+ for (auto &cr : curRay) {
+ cr.start.x = (offset.x + SCREEN_WIDTH / 2);
+ cr.start.y = offset.y - (a * itemWide * 1.5f);
+ curCurCoord[a++] = cr.start;
+ } a = 0;
+
+ for (int r = 0; r < 4; r++) {
+ for (int c = 0; c < 8; c++) {
+ massRay[a ].x = ((offset.x - SCREEN_WIDTH / 2) + itemWide) + c * itemWide * 1.5f;
+ massRay[a++].y = ((offset.y + SCREEN_HEIGHT / 2) - itemWide * 1.5f) - r * itemWide * 1.5f;
+ }
+ } a = 0;
+
+ auto averagef = [](const std::vector<int> &v) {
+ auto sum = std::accumulate(std::begin(v), std::end(v), 0);
+ return sum / v.size();
+ };
+
+ ui::fontTransInv = std::clamp(255 * (averagef(dfp) / range), 0ul, 255ul);
+
+ if (invOpening) {
+ for (auto &d : dfp) {
+ if (!a || dfp[a - 1] > 50)
+ d += 4.0f * deltaTime;
+ if (d > range)
+ d = range;
+ a++;
+ } a = 0;
+
+ for (auto &cd : curdfp) {
+ if (!a || curdfp[a - 1] > 90)
+ cd += 3.0f * deltaTime;
+ if (cd > curRange)
+ cd = curRange;
+ a++;
+ } a = 0;
+
+ while (a < massOrder.size()) {
+ if (!a || massDfp[massOrder[a - 1]] > massRange * 0.75f)
+ massDfp[massOrder[a]] += 20.0f * deltaTime;
+ if (massDfp[massOrder[a]] > massRange)
+ massDfp[massOrder[a]] = massRange;
+ a++;
+ } a = 0;
+
+ if (numSlot > 0)
+ invOpen = true;
+ } else {
+ for (auto &d : dfp) {
+ if (d > 0)
+ d -= 4.5f * deltaTime;
+ }
+ for (auto &cd : curdfp) {
+ if (cd > 0)
+ cd -= 3.0f * deltaTime;
+ }
+
+ while (a < massRay.size()) {
+ if (!a || massDfp[massOrderClosing[a - 1]] <= 0)
+ massDfp[massOrderClosing[a]] -= 30.0f * deltaTime;
+ else if (massDfp[massOrderClosing[a - 1]] < 0)
+ massDfp[massOrderClosing[a - 1]] = 0;
+ a++;
+ } a = 0;
+
+ if (std::all_of(std::begin(massDfp), std::end(massDfp), [](auto d) { return d <= 0; })) {
+ invOpen = false;
+ for (auto &md : massDfp) {
+ if (md < 0)
+ md = 0;
+ }
+ }
+
+ }
+
+ /*
+ * a = 0
+ */
+
+ if (invOpen) {
+ Render::useShader(&Render::textShader);
+ for(auto &mr : massRay) {
+ float t = (((float)massDfp[a]/(float)massRange)*.5f);
+ glActiveTexture(GL_TEXTURE0);
+ Render::textShader.use();
+
+ glBindTexture(GL_TEXTURE_2D, Texture::genColor(Color(0.0f,0.0f,0.0f, t >= 0? 255*t : 0)));
+ glUniform1i(Render::textShader.uniform[WU_texture], 0);
+
+ Render::drawRect(vec2(mr.x-(itemWide/2), mr.y-(itemWide/2)), vec2(mr.x-(itemWide/2)+itemWide, mr.y-(itemWide/2)+itemWide), -6.0);
+
+ glUseProgram(0);
+ if (!Items.empty() && a+numSlot < Items.size() && Items[a+numSlot].second) {
+ Render::textShader.use();
+ glBindTexture(GL_TEXTURE_2D, Items[a+numSlot].first->tex->image[0]);//itemtex[items[a+numSlot].id]);
+ glUniform4f(Render::textShader.uniform[WU_tex_color], 1.0f, 1.0f, 1.0f, ((float)massDfp[a]/(float)(massRange?massRange:1))*0.8f);
+
+ if (Items[a+numSlot].first->dim.y > Items[a+numSlot].first->dim.x) {
+ Render::drawRect(vec2(mr.x-((itemWide/2)*((float)Items[a+numSlot].first->dim.x/(float)Items[a+numSlot].first->dim.y)), mr.y-(itemWide/2)),
+ vec2(mr.x+((itemWide/2)*((float)Items[a+numSlot].first->dim.x/(float)Items[a+numSlot].first->dim.y)), mr.y+(itemWide/2)), -6.1);
+ } else {
+ Render::drawRect(vec2(mr.x-(itemWide/2),mr.y-(itemWide/2)*((float)Items[a+numSlot].first->dim.y/(float)Items[a+numSlot].first->dim.x)),
+ vec2(mr.x-(itemWide/2),mr.y+(itemWide/2)*((float)Items[a+numSlot].first->dim.y/(float)Items[a+numSlot].first->dim.x)), -6.1);
+ }
+ ui::setFontColor(255,255,255,((float)massDfp[a]/(float)(massRange?massRange:1))*255);
+ ui::putText(mr.x-(itemWide/2)+(itemWide*.85),mr.y-(itemWide/2),"%d",Items[a+numSlot].second);
+ ui::setFontColor(255,255,255,255);
+ Render::textShader.unuse();
+ }
+ a++;
+ }a=0;
+
+ for(auto &cr : curRay) {
+ curCurCoord[a].x -= float((curdfp[a]) * cos(-1));
+ curCurCoord[a].y += float((curdfp[a]) * sin(0));
+ cr.end = curCurCoord[a];
+
+ float curTrans = (((float)curdfp[a]/(float)(curRange?curRange:1))*0.5f);
+
+ Render::textShader.use();
+ glBindTexture(GL_TEXTURE_2D, Texture::genColor(Color(0.0f, 0.0f, 0.0f, curTrans >= 0 ? 255 * curTrans : 0)));
+ Render::drawRect(vec2(cr.end.x-(itemWide/2), cr.end.y-(itemWide/2)),
+ vec2(cr.end.x-(itemWide/2)+itemWide,cr.end.y-(itemWide/2)+itemWide), -6.0);
+ Render::textShader.unuse();
+ a++;
+ }a=0;
+
+ for(auto &r : iray) {
+ angle = 180 - (angleB * a) - angleB / 2.0f;
+ curCoord[a].x += float((dfp[a]) * cos(angle*PI/180));
+ curCoord[a].y += float((dfp[a]) * sin(angle*PI/180));
+ r.end = curCoord[a];
+
+ float t = ((float)dfp[a]/(float)(range?range:1))*0.5f;
+
+ Render::textShader.use();
+ glBindTexture(GL_TEXTURE_2D, Texture::genColor(Color(0.0f, 0.0f, 0.0f, t >= 0 ? 255 * t : 0)));
+ Render::drawRect(vec2(r.end.x-(itemWide/2), r.end.y-(itemWide/2)),
+ vec2(r.end.x-(itemWide/2)+itemWide,r.end.y-(itemWide/2)+itemWide), -6.0);
+
+ if (!Items.empty() && a < numSlot && Items[a].second) {
+ glBindTexture(GL_TEXTURE_2D, Items[a].first->tex->image[0]);//itemtex[items[a].id]);
+ glUniform4f(Render::textShader.uniform[WU_tex_color], 1.0f, 1.0f, 1.0f, ((float)dfp[a]/(float)(range?range:1))*0.8f);
+ if (Items[a].first->dim.y > Items[a].first->dim.x) {
+ Render::drawRect(vec2(r.end.x-((itemWide/2)*((float)Items[a].first->dim.x/(float)Items[a].first->dim.y)), r.end.y-(itemWide/2)),
+ vec2(r.end.x+((itemWide/2)*((float)Items[a].first->dim.x/(float)Items[a].first->dim.y)), r.end.y+(itemWide/2)), -6.1);
+ } else {
+ Render::drawRect(vec2(r.end.x-(itemWide/2),r.end.y-(itemWide/2)*((float)Items[a].first->dim.y/(float)Items[a].first->dim.x)),
+ vec2(r.end.x+(itemWide/2),r.end.y+(itemWide/2)*((float)Items[a].first->dim.y/(float)Items[a].first->dim.x)), -6.1);
+ }
+ ui::setFontColor(255,255,255,((float)dfp[a]/(float)(range?range:1))*255);
+ ui::putStringCentered(r.end.x,r.end.y-(itemWide*.9),Items[a].first->name);//itemMap[items[a].id]->name);
+ ui::putText(r.end.x-(itemWide/2)+(itemWide*.85),r.end.y-(itemWide/2),"%d",Items[a].second);
+ ui::setFontColor(255,255,255,255);
+ }
+ Render::textShader.unuse();
+ if (sel == a) {
+ static float sc = 1;
+ static bool up;
+ up ? sc += .0025*deltaTime : sc -= .0025*deltaTime;
+ if (sc > 1.2) {
+ up = false;
+ sc = 1.2;
+ }
+ if (sc < 1.0) {
+ up = true;
+ sc = 1.0;
+ }
+ float t = ((float)dfp[a]/(float)(range?range:1));
+ Render::useShader(&Render::textShader);
+
+ Render::textShader.use();
+ glUniform4f(Render::textShader.uniform[WU_tex_color], 1.0, 1.0, 1.0, 1.0);
+
+ // bottom
+ glBindTexture(GL_TEXTURE_2D, Texture::genColor(Color(255, 255, 255, t >= 0 ? 255 * t : 0)));
+ Render::drawRect(vec2(r.end.x - (itemWide*sc)/2 - (itemWide*sc)*.09,r.end.y - (itemWide*sc)/2 - (itemWide*sc)*.09),
+ vec2(r.end.x + (itemWide*sc)/2 + (itemWide*sc)*.09,r.end.y - (itemWide*sc)/2), -6.2);
+
+ // top
+ glBindTexture(GL_TEXTURE_2D, Texture::genColor(Color(255, 255, 255, t >= 0 ? 255 * t : 0)));
+ Render::drawRect(vec2(r.end.x - (itemWide*sc)/2 - (itemWide*sc)*.09,r.end.y + (itemWide*sc)/2 + (itemWide*sc)*.09),
+ vec2(r.end.x + (itemWide*sc)/2 + (itemWide*sc)*.09,r.end.y + (itemWide*sc)/2), -6.2);
+
+ // left
+ glBindTexture(GL_TEXTURE_2D, Texture::genColor(Color(255, 255, 255, t >= 0 ? 255 * t : 0)));
+ Render::drawRect(vec2(r.end.x - (itemWide*sc)/2 - (itemWide*sc)*.09,r.end.y - (itemWide*sc)/2 - (itemWide*sc)*.09),
+ vec2(r.end.x - (itemWide*sc)/2 ,r.end.y + (itemWide*sc)/2 + (itemWide*sc)*.09), -6.2);
+
+ // right
+ glBindTexture(GL_TEXTURE_2D, Texture::genColor(Color(255, 255, 255, t >= 0 ? 255 * t : 0)));
+ Render::drawRect(vec2(r.end.x + (itemWide*sc)/2 ,r.end.y - (itemWide*sc)/2 - (itemWide*sc)*.09),
+ vec2(r.end.x + (itemWide*sc)/2 + (itemWide*sc)*.09,r.end.y + (itemWide*sc)/2 + (itemWide*sc)*.09), -6.2);
+
+ //glUseProgram(0);
+ }
+ a++;
+ }
+ } /*else if (invHover) {
+ static unsigned int highlight = 0;
+ static unsigned int thing = 0;
+
+ if (!mouseSel) {
+ // setup?
+ mouseStart.x = ui::mouse.x - offset.x;
+ highlight = sel;
+ thing = sel;
+ mouseSel = true;
+ } else {
+ if((ui::mouse.x - offset.x) >= mouseStart.x){
+ thing = (ui::mouse.x - offset.x - mouseStart.x)/80;
+ highlight=sel+thing;
+ if(highlight>numSlot-1)highlight=numSlot-1;
+ if(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_LEFT)){
+ sel = highlight;
+ mouseSel=false;
+ invHover=false;
+ selected = true;
+ }
+ }
+ if ((ui::mouse.x - offset.x) < mouseStart.x) {
+ thing = (mouseStart.x - (ui::mouse.x - offset.x))/80;
+ if ((int)sel - (int)thing < 0)
+ highlight = 0;
+ else
+ highlight = sel - thing;
+ if(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_LEFT)){
+ sel = highlight;
+ mouseSel=false;
+ invHover=false;
+ selected = true;
+ }
+ }
+ }
+
+ a = 0;
+ for (auto &r : iray) {
+ angle = 180 - (angleB * a) - angleB / 2.0f;
+ curCoord[a].x += float(range) * cos(angle*PI/180);
+ curCoord[a].y += float(range) * sin(angle*PI/180);
+ r.end = curCoord[a];
+
+ // square drawing
+ glColor4f(0.0f, 0.0f, 0.0f, a == highlight ? 0.5f : 0.1f);
+ glBegin(GL_QUADS);
+ glVertex2i(r.end.x-(itemWide/2), r.end.y-(itemWide/2));
+ glVertex2i(r.end.x+(itemWide/2), r.end.y-(itemWide/2));
+ glVertex2i(r.end.x+(itemWide/2), r.end.y+(itemWide/2));
+ glVertex2i(r.end.x-(itemWide/2), r.end.y+(itemWide/2));
+ glEnd();
+
+ if (a < items.size() && items[a].count) {
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, itemtex[items[a].id]);
+ glColor4f(1.0f, 1.0f, 1.0f, a == highlight ? 0.8f : 0.2f);
+ glBegin(GL_QUADS);
+ if(itemMap[items[a].id]->height > itemMap[items[a].id]->width){
+ glTexCoord2i(0,1);glVertex2i(r.end.x-((itemWide/2)*((float)itemMap[items[a].id]->width/(float)itemMap[items[a].id]->height)),r.end.y-(itemWide/2));
+ glTexCoord2i(1,1);glVertex2i(r.end.x+((itemWide/2)*((float)itemMap[items[a].id]->width/(float)itemMap[items[a].id]->height)),r.end.y-(itemWide/2));
+ glTexCoord2i(1,0);glVertex2i(r.end.x+((itemWide/2)*((float)itemMap[items[a].id]->width/(float)itemMap[items[a].id]->height)),r.end.y+(itemWide/2));
+ glTexCoord2i(0,0);glVertex2i(r.end.x-((itemWide/2)*((float)itemMap[items[a].id]->width/(float)itemMap[items[a].id]->height)),r.end.y+(itemWide/2));
+ }else{
+ glTexCoord2i(0,1);glVertex2i(r.end.x-(itemWide/2),r.end.y-(itemWide/2)*((float)itemMap[items[a].id]->height/(float)itemMap[items[a].id]->width));
+ glTexCoord2i(1,1);glVertex2i(r.end.x+(itemWide/2),r.end.y-(itemWide/2)*((float)itemMap[items[a].id]->height/(float)itemMap[items[a].id]->width));
+ glTexCoord2i(1,0);glVertex2i(r.end.x+(itemWide/2),r.end.y+(itemWide/2)*((float)itemMap[items[a].id]->height/(float)itemMap[items[a].id]->width));
+ glTexCoord2i(0,0);glVertex2i(r.end.x-(itemWide/2),r.end.y+(itemWide/2)*((float)itemMap[items[a].id]->height/(float)itemMap[items[a].id]->width));
+ }
+ glEnd();
+ glDisable(GL_TEXTURE_2D);
+ }
+ a++;
+ }
+
+ if (highlight < items.size()) {
+ ui::putStringCentered(player->loc.x + player->width / 2,
+ player->loc.y + range * 0.75f,
+ itemMap[items[highlight].id]->name
+ );
+ }
+ }*/
+ /*if (!items.empty() && items.size() > sel && items[sel].count)
+ itemDraw(player,items[sel].id);*/
+ if (!Items.empty() && Items.size() > sel && Items[sel].second)
+ itemDraw(player, Items[sel].first);
+}
+
+void itemDraw(Player *p, Item *d) {
+
+ itemLoc.y = p->loc.y+(p->height/3);
+ itemLoc.x = p->left?p->loc.x-d->dim.x/2:p->loc.x+p->width-d->dim.x/2;
+
+ Render::worldShader.use();
+
+ if (p->left) {
+ // move to center of screen
+ glm::mat4 tro = glm::translate(glm::mat4(1.0f),
+ glm::vec3(itemLoc.x+d->dim.x/2, itemLoc.y, 0));
+ // rotate off center
+ glm::mat4 rot = glm::rotate(glm::mat4(1.0f),
+ static_cast<GLfloat>((d->rotation*3.14159)/180.0f),
+ glm::vec3(0.0f, 0.0f, 1.0f));
+ // move back to player
+ glm::mat4 trt = glm::translate(glm::mat4(1.0f),
+ glm::vec3(-itemLoc.x-d->dim.x/2, -itemLoc.y, 0));
+ // tell shader to translate the object using steps above
+ glUniformMatrix4fv(Render::worldShader.uniform[WU_transform], 1, GL_FALSE, glm::value_ptr(tro * rot * trt));
+ } else {
+ // move to center of screen
+ glm::mat4 tro = glm::translate(glm::mat4(1.0f),
+ glm::vec3(itemLoc.x+d->dim.x/2,itemLoc.y,0));
+ // rotate off center
+ glm::mat4 rot = glm::rotate(glm::mat4(1.0f),
+ static_cast<GLfloat>((d->rotation*3.14159)/180.0f),
+ glm::vec3(0.0f, 0.0f, 1.0f));
+ // move back to player
+ glm::mat4 trt = glm::translate(glm::mat4(1.0f),
+ glm::vec3(-itemLoc.x-d->dim.x/2,-itemLoc.y,0));
+ // tell shader to translate the object using steps above
+ glUniformMatrix4fv(Render::worldShader.uniform[WU_transform], 1, GL_FALSE, glm::value_ptr(tro * rot * trt));
+ }
+
+ GLfloat itemTex[12] = {0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+
+ 1.0, 1.0,
+ 0.0, 1.0,
+ 0.0, 0.0};
+ if (!p->left) {
+ itemTex[0] = 1.0;
+ itemTex[2] = 0.0;
+ itemTex[4] = 0.0;
+ itemTex[6] = 0.0;
+ itemTex[8] = 1.0;
+ itemTex[10] = 1.0;
+ }
+
+ GLfloat itemCoords[] = {itemLoc.x, itemLoc.y, p->z,
+ itemLoc.x+d->dim.x, itemLoc.y, p->z,
+ itemLoc.x+d->dim.x, itemLoc.y+d->dim.y, p->z,
+
+ itemLoc.x+d->dim.x, itemLoc.y+d->dim.y, p->z,
+ itemLoc.x, itemLoc.y+d->dim.y, p->z,
+ itemLoc.x, itemLoc.y, p->z};
+
+ glBindTexture(GL_TEXTURE_2D,d->tex->image[0]);
+
+ Render::worldShader.enable();
+
+ glVertexAttribPointer(Render::worldShader.coord, 3, GL_FLOAT, GL_FALSE, 0, itemCoords);
+ glVertexAttribPointer(Render::worldShader.tex, 2, GL_FLOAT, GL_FALSE, 0, itemTex);
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+
+ Render::worldShader.disable();
+ Render::worldShader.unuse();
+}
+
+/*
+ * This function is used to trigger the player's item's ability.
+ */
+int Inventory::useItem(void)
+{
+ return 0;
+}
+
+int Inventory::useCurrent()
+{
+ if (Items[sel].second)
+ return Items[sel].first->useItem();
+ return -1;
+}
+
+void Inventory::currentAddInteract(Entity* e)
+{
+ if (Items[sel].second)
+ Items[sel].first->addInteract(e);
+}
+
+void Inventory::currentAddInteract(std::vector<Entity*> e)
+{
+ if (Items[sel].second)
+ Items[sel].first->addInteract(e);
+}
+
+bool Inventory::detectCollision(vec2 one, vec2 two) {
+ (void)one;
+ (void)two;
+ return false;
+}
+
+const Item* Inventory::getCurrentItem(void)
+{
+ if (Items.size() > 0)
+ return Items[sel].first;
+ else
+ return nullptr;
+}
+
+void InventorySystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt)
+{
+ (void)en;
+ (void)ev;
+ (void)dt;
+}
+
+void InventorySystem::configure(entityx::EventManager &em)
+{
+ em.subscribe<MouseScrollEvent>(*this);
+}
+
+void InventorySystem::receive(const MouseScrollEvent &mse)
+{
+ static int mouseWheelUpCount = 0, mouseWheelDownCount = 0;
+
+ if ((mse.scrollDistance < 0) && ((++mouseWheelUpCount % 5) == 0) ) {
+ mouseWheelUpCount = 0;
+ player->inv->setSelectionUp();
+ } else if ( (++mouseWheelDownCount % 5) == 0 ) {
+ mouseWheelDownCount = 0;
+ player->inv->setSelectionDown();
+ }
+}
+++ /dev/null
-#include <inventory.hpp>
-#include <entities.hpp>
-#include <world.hpp>
-
-extern Player *player;
-extern World *currentWorld;
-
-/************************************************************************************
-* GLOBAL *
-************************************************************************************/
-
-/**************************************************
-* USE ITEM *
-**************************************************/
-
-int BaseItem::useItem()
-{
- return 0;
-}
-
-int Sword::useItem()
-{
- if (inUse())
- return -1;
-
- std::thread([this]{
- setUse(true);
- volatile bool swing = true;
- bool back = false;
- float coef = 0.0f;
-
- while (swing) {
-
- // handle swinging
- if (!back)
- coef += .8f;
- else
- coef -= .4f;
-
- if (player->left)
- rotation = coef;
- else
- rotation = -coef;
-
- if (coef > 80 && !back)
- back = true;
-
- if (coef <= 0 && back) {
- swing = false;
- coef = 0.0f;
- rotation = 0.0f;
- }
-
- if (!back) {
- // handle collision with interaction
- hitbox.start.y = player->loc.y+(player->height/3);
- hitbox.start.x = player->left ? player->loc.x : player->loc.x + player->width;
-
- for (auto &e : interact) {
- float dist = 0.0f;
- while (dist < dim.y) {
- hitbox.end = hitbox.start;
- if (player->left)
- hitbox.end.x -= dist * cos(rotation*PI/180);
- else
- hitbox.end.x += dist * cos(rotation*PI/180);
-
- hitbox.end.y += dist * sin(rotation*PI/180);
-
- if (hitbox.end.x > e->loc.x && hitbox.end.x < e->loc.x + e->width) {
- if (hitbox.end.y > e->loc.y && hitbox.end.y < e->loc.y + e->height) {
- if (e->type == MOBT)
- Mobp(e)->onHit(damage);
- else
- e->takeHit(damage, 600);
-
- // add some blood
- //for(int r = 0; r < (rand()%5);r++)
- //currentWorld->addParticle(rand()%game::HLINE*3 + e->loc.x - .05f,e->loc.y + e->height*.5, game::HLINE,game::HLINE, -(rand()%10)*.01,((rand()%4)*.001-.002), {(rand()%75+10)/100.0f,0,0}, 10000);
- }
- }
-
- dist += HLINES(0.5f);
- }
- }
- }
-
- // add a slight delay
- SDL_Delay(1);
- }
- for (auto &e : interact)
- e->setCooldown(0);
- setUse(false);
- }).detach();
-
- return 0;
-}
-
-int Arrow::useItem()
-{
-
- return 0;
-}
-
-int Bow::useItem()
-{
- if (inUse())
- return -1;
-
- std::thread([this](void) {
- setUse(true);
-
- static Particles* part = nullptr;
-
- if (part == nullptr) {
- float rot = atan(sqrt(pow(ui::mouse.y-(player->loc.y + player->height),2)/pow(ui::mouse.x-player->loc.x,2)));
- float speed = 1.0;
- float vx = speed * cos(rot);
- float vy = speed * sin(rot);
-
- vx *= (ui::mouse.x < player->loc.x) ? -1 : 1;
- vy *= (ui::mouse.y < player->loc.y + player->height) ? -1 : 1;
-
- currentWorld->addParticle(player->loc.x, // x
- player->loc.y + player->height, // y
- HLINES(3), // width
- HLINES(3), // height
- vx, // vel.x
- vy, // vel.y
- {139, 69, 19}, // RGB color
- 2500 // duration (ms)
- );
- part = ¤tWorld->particles.back();
- } else {
- if (part->vel.x < 0.05 && part->vel.y < 0.05) {
- part->duration = 0;
- part = nullptr;
- }
- }
-
- setUse(false);
- }).detach();
-
- return 0;
-}
-
-// TODO chance to hurt
-int RawFood::useItem()
-{
- return 0;
-}
-
-int Food::useItem()
-{
- std::cout << "Yum!" << std::endl;
- return 0;
-}
-
-int ItemLight::useItem()
-{
- if (player->light.radius > 0)
- player->light.radius = 0;
- else
- player->light.radius = 500;
- return 0;
-}
-
-/**************************************************
-* CLONE *
-**************************************************/
-
-BaseItem* BaseItem::clone()
-{
- return new BaseItem(*this);
-}
-
-Sword* Sword::clone()
-{
- return new Sword(*this);
-}
-
-Arrow* Arrow::clone()
-{
- return new Arrow(*this);
-}
-
-Bow* Bow::clone()
-{
- return new Bow(*this);
-}
-
-Food* Food::clone()
-{
- return new Food(*this);
-}
-
-RawFood* RawFood::clone()
-{
- return new RawFood(*this);
-}
-
-ItemLight* ItemLight::clone()
-{
- return new ItemLight(*this);
-}
-/************************************************************************************
-* ITEM SPECIFIC *
-************************************************************************************/
-
-/**************************************************
-* ITEM *
-**************************************************/
-
-bool Item::inUse()
-{
- return beingUsed;
-}
-
-void Item::setUse(bool use)
-{
- beingUsed = use;
-}
-
-void Item::addInteract(Entity* e)
-{
- interact.push_back(e);
-}
-
-void Item::addInteract(std::vector<Entity*> e)
-{
- for (auto &v : e) {
- interact.push_back(v);
- }
-}
-
-GLuint Item::rtex()
-{
- return tex->image[0];
-}
-
-GLuint Item::rtex(int n)
-{
- return tex->image[n];
-}
-
-Item::~Item()
-{
- delete tex;
-}
-
-/**************************************************
-* SWORD *
-**************************************************/
-
-float Sword::getDamage()
-{
- return damage;
-}
-
-void Sword::setDamage(float d)
-{
- damage = d;
-}
-
-/**************************************************
-* ARROW *
-**************************************************/
-
-float Arrow::getDamage()
-{
- return damage;
-}
-
-void Arrow::setDamage(float d)
-{
- damage = d;
-}
-
-
-/**************************************************
-* BOW *
-**************************************************/
-
-float Bow::getDamage()
-{
- return damage;
-}
-
-void Bow::setDamage(float d)
-{
- damage = d;
-}
-
-/**************************************************
-* FOODS *
-**************************************************/
-
-float RawFood::getHealth()
-{
- return health;
-}
--- /dev/null
+#include <inventory.hpp>
+#include <entities.hpp>
+#include <world.hpp>
+
+extern Player *player;
+extern World *currentWorld;
+
+/************************************************************************************
+* GLOBAL *
+************************************************************************************/
+
+/**************************************************
+* USE ITEM *
+**************************************************/
+
+int BaseItem::useItem()
+{
+ return 0;
+}
+
+int Sword::useItem()
+{
+ if (inUse())
+ return -1;
+
+ std::thread([this]{
+ setUse(true);
+ volatile bool swing = true;
+ bool back = false;
+ float coef = 0.0f;
+
+ while (swing) {
+
+ // handle swinging
+ if (!back)
+ coef += .8f;
+ else
+ coef -= .4f;
+
+ if (player->left)
+ rotation = coef;
+ else
+ rotation = -coef;
+
+ if (coef > 80 && !back)
+ back = true;
+
+ if (coef <= 0 && back) {
+ swing = false;
+ coef = 0.0f;
+ rotation = 0.0f;
+ }
+
+ if (!back) {
+ // handle collision with interaction
+ hitbox.start.y = player->loc.y+(player->height/3);
+ hitbox.start.x = player->left ? player->loc.x : player->loc.x + player->width;
+
+ for (auto &e : interact) {
+ float dist = 0.0f;
+ while (dist < dim.y) {
+ hitbox.end = hitbox.start;
+ if (player->left)
+ hitbox.end.x -= dist * cos(rotation*PI/180);
+ else
+ hitbox.end.x += dist * cos(rotation*PI/180);
+
+ hitbox.end.y += dist * sin(rotation*PI/180);
+
+ if (hitbox.end.x > e->loc.x && hitbox.end.x < e->loc.x + e->width) {
+ if (hitbox.end.y > e->loc.y && hitbox.end.y < e->loc.y + e->height) {
+ if (e->type == MOBT)
+ Mobp(e)->onHit(damage);
+ else
+ e->takeHit(damage, 600);
+
+ // add some blood
+ //for(int r = 0; r < (rand()%5);r++)
+ //currentWorld->addParticle(rand()%game::HLINE*3 + e->loc.x - .05f,e->loc.y + e->height*.5, game::HLINE,game::HLINE, -(rand()%10)*.01,((rand()%4)*.001-.002), {(rand()%75+10)/100.0f,0,0}, 10000);
+ }
+ }
+
+ dist += HLINES(0.5f);
+ }
+ }
+ }
+
+ // add a slight delay
+ SDL_Delay(1);
+ }
+ for (auto &e : interact)
+ e->setCooldown(0);
+ setUse(false);
+ }).detach();
+
+ return 0;
+}
+
+int Arrow::useItem()
+{
+
+ return 0;
+}
+
+int Bow::useItem()
+{
+ if (inUse())
+ return -1;
+
+ std::thread([this](void) {
+ setUse(true);
+
+ static Particles* part = nullptr;
+
+ if (part == nullptr) {
+ float rot = atan(sqrt(pow(ui::mouse.y-(player->loc.y + player->height),2)/pow(ui::mouse.x-player->loc.x,2)));
+ float speed = 1.0;
+ float vx = speed * cos(rot);
+ float vy = speed * sin(rot);
+
+ vx *= (ui::mouse.x < player->loc.x) ? -1 : 1;
+ vy *= (ui::mouse.y < player->loc.y + player->height) ? -1 : 1;
+
+ currentWorld->addParticle(player->loc.x, // x
+ player->loc.y + player->height, // y
+ HLINES(3), // width
+ HLINES(3), // height
+ vx, // vel.x
+ vy, // vel.y
+ {139, 69, 19}, // RGB color
+ 2500 // duration (ms)
+ );
+ part = ¤tWorld->particles.back();
+ } else {
+ if (part->vel.x < 0.05 && part->vel.y < 0.05) {
+ part->duration = 0;
+ part = nullptr;
+ }
+ }
+
+ setUse(false);
+ }).detach();
+
+ return 0;
+}
+
+// TODO chance to hurt
+int RawFood::useItem()
+{
+ return 0;
+}
+
+int Food::useItem()
+{
+ std::cout << "Yum!" << std::endl;
+ return 0;
+}
+
+int ItemLight::useItem()
+{
+ if (player->light.radius > 0)
+ player->light.radius = 0;
+ else
+ player->light.radius = 500;
+ return 0;
+}
+
+/**************************************************
+* CLONE *
+**************************************************/
+
+BaseItem* BaseItem::clone()
+{
+ return new BaseItem(*this);
+}
+
+Sword* Sword::clone()
+{
+ return new Sword(*this);
+}
+
+Arrow* Arrow::clone()
+{
+ return new Arrow(*this);
+}
+
+Bow* Bow::clone()
+{
+ return new Bow(*this);
+}
+
+Food* Food::clone()
+{
+ return new Food(*this);
+}
+
+RawFood* RawFood::clone()
+{
+ return new RawFood(*this);
+}
+
+ItemLight* ItemLight::clone()
+{
+ return new ItemLight(*this);
+}
+/************************************************************************************
+* ITEM SPECIFIC *
+************************************************************************************/
+
+/**************************************************
+* ITEM *
+**************************************************/
+
+bool Item::inUse()
+{
+ return beingUsed;
+}
+
+void Item::setUse(bool use)
+{
+ beingUsed = use;
+}
+
+void Item::addInteract(Entity* e)
+{
+ interact.push_back(e);
+}
+
+void Item::addInteract(std::vector<Entity*> e)
+{
+ for (auto &v : e) {
+ interact.push_back(v);
+ }
+}
+
+GLuint Item::rtex()
+{
+ return tex->image[0];
+}
+
+GLuint Item::rtex(int n)
+{
+ return tex->image[n];
+}
+
+Item::~Item()
+{
+ delete tex;
+}
+
+/**************************************************
+* SWORD *
+**************************************************/
+
+float Sword::getDamage()
+{
+ return damage;
+}
+
+void Sword::setDamage(float d)
+{
+ damage = d;
+}
+
+/**************************************************
+* ARROW *
+**************************************************/
+
+float Arrow::getDamage()
+{
+ return damage;
+}
+
+void Arrow::setDamage(float d)
+{
+ damage = d;
+}
+
+
+/**************************************************
+* BOW *
+**************************************************/
+
+float Bow::getDamage()
+{
+ return damage;
+}
+
+void Bow::setDamage(float d)
+{
+ damage = d;
+}
+
+/**************************************************
+* FOODS *
+**************************************************/
+
+float RawFood::getHealth()
+{
+ return health;
+}
+++ /dev/null
-#include <mob.hpp>
-#include <ui.hpp>
-#include <world.hpp>
-#include <brice.hpp>
-
-extern World *currentWorld;
-
-Mob::Mob(void)
-{
- type = MOBT;
- inv = nullptr;
- rider = nullptr;
- xmle = nullptr;
- canMove = true;
- loc = 0;
-}
-
-Page::Page(void) : Mob()
-{
-
- ridable = false;
- aggressive = false;
- maxHealth = health = 50;
- width = HLINES(6);
- height = HLINES(4);
- tex = TextureIterator({"assets/items/ITEM_PAGE.png"});
- pageTexture = 0;
-}
-
-void Page::act(void)
-{
- if (player->loc.x > loc.x - 100 && player->loc.x < loc.x + 100 && isInside(ui::mouse) &&
- (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_RIGHT))) {
- std::thread([this](void){
- ui::drawPage(pageTexture);
- ui::waitForDialog();
- game::setValue(cId, cValue);
- game::briceUpdate();
- die();
- }).detach();
- }
-}
-
-void Page::onHit(unsigned int _health)
-{
- (void)_health;
- act();
-}
-
-bool Page::bindTex(void)
-{
- glActiveTexture(GL_TEXTURE0);
- tex(0);
- return true;
-}
-
-void Page::createFromXML(XMLElement *e, World *w=nullptr)
-{
- (void)w;
- float Xlocx;
- if (e->QueryFloatAttribute("x", &Xlocx) == XML_NO_ERROR)
- loc.x = Xlocx;
- pageTexPath = e->StrAttribute("id");
- pageTexture = Texture::loadTexture(pageTexPath);
-
- cId = e->StrAttribute("cid");
- cValue = e->StrAttribute("cvalue");
-
- xmle = e;
-}
-
-void Page::saveToXML(void)
-{}
-
-Door::Door(void) : Mob()
-{
- ridable = false;
- aggressive = false;
- maxHealth = health = 50;
- width = HLINES(12);
- height = HLINES(20);
- tex = TextureIterator({"assets/style/classic/door.png"});
-}
-
-void Door::act(void)
-{
-}
-
-void Door::onHit(unsigned int _health)
-{
- (void)_health;
-}
-
-bool Door::bindTex(void)
-{
- glActiveTexture(GL_TEXTURE0);
- tex(0);
- return true;
-}
-
-void Door::createFromXML(XMLElement *e, World *w=nullptr)
-{
- (void)w;
- float Xlocx;
- if (e->QueryFloatAttribute("x", &Xlocx) == XML_NO_ERROR)
- loc.x = Xlocx;
-}
-
-void Door::saveToXML(void)
-{}
-
-Cat::Cat(void) : Mob()
-{
- ridable = true;
- aggressive = false;
- maxHealth = health = 100000;
- width = HLINES(19);
- height = HLINES(15);
- tex = TextureIterator({"assets/cat.png"});
- actCounterInitial = 0;
- actCounter = 1;
-}
-
-void Cat::act(void)
-{
- static float vely = 0;
- if (rider != nullptr) {
- if (!rider->ground) {
- loc.y += HLINES(2);
- vel.y = .4;
- }
- if (rider->speed > 1) {
- vely = .5;
- } else if (rider->speed == .5) {
- vely = -.5;
- } else {
- vely = 0;
- }
- vel.y = vely;
- if (!rider->ground) {
- if ((vel.y -= .015) < -.2)
- rider->ground = true;
- }
- vel.x = .1 * (rider->left ? -1 : 1);
- } else {
- vel = 0;
- }
-}
-
-void Cat::onHit(unsigned int _health)
-{
- health += _health;
-}
-
-bool Cat::bindTex(void)
-{
- glActiveTexture(GL_TEXTURE0);
- tex(0);
- return true;
-}
-
-void Cat::createFromXML(XMLElement *e, World *w=nullptr)
-{
- (void)w;
- float spawnc;
-
- if (e->QueryFloatAttribute("x", &spawnc) == XML_NO_ERROR)
- loc.x = spawnc;
- else
- loc.x = e->FloatAttribute("spawnx");
-
- if (e->QueryFloatAttribute("y", &spawnc) == XML_NO_ERROR)
- loc.y = spawnc;
-
- xmle = e;
-}
-
-void Cat::saveToXML(void)
-{
- E_SAVE_COORDS;
- xmle->SetAttribute("alive", alive);
-}
-
-Rabbit::Rabbit(void) : Mob()
-{
- ridable = true;
- aggressive = false;
- maxHealth = health = 50;
- width = HLINES(10);
- height = HLINES(8);
- tex = TextureIterator({"assets/rabbit.png", "assets/rabbit1.png"});
- actCounterInitial = randGet() % 240 + 15;
- actCounter = 1;
-
- drop = {
- std::make_tuple("Dank MayMay", 5, 1.00f)
- };
-}
-
-void Rabbit::act(void)
-{
- static int direction = 0;
-
- if (!--actCounter) {
- actCounter = actCounterInitial;
- direction = (randGet() % 3 - 1); //sets the direction to either -1, 0, 1
- if (direction == 0)
- ticksToUse /= 2;
- vel.x *= direction;
- }
-
- if (ground && direction) {
- ground = false;
- vel.y = .15;
- loc.y += HLINES(0.25f);
- vel.x = 0.05f * direction;
- }
-}
-
-void Rabbit::onHit(unsigned int _health)
-{
- takeHit(_health, 600);
-}
-
-bool Rabbit::bindTex(void)
-{
- glActiveTexture(GL_TEXTURE0);
- tex(!ground);
- return true;
-}
-
-void Rabbit::createFromXML(XMLElement *e, World *w=nullptr)
-{
- (void)w;
- float spawnc;
-
- xmle = e;
-
- if (e->QueryFloatAttribute("x", &spawnc) == XML_NO_ERROR)
- loc.x = spawnc;
- else
- loc.x = e->FloatAttribute("spawnx");
-
- if (e->QueryFloatAttribute("y", &spawnc) == XML_NO_ERROR)
- loc.y = spawnc;
-
- E_LOAD_HEALTH;
-
- if (e->QueryBoolAttribute("aggressive", &aggressive) != XML_NO_ERROR)
- aggressive = false;
-}
-
-void Rabbit::saveToXML(void)
-{
- E_SAVE_HEALTH;
-}
-
-Bird::Bird(void) : Mob()
-{
- ridable = true;
- aggressive = false;
- maxHealth = health = 50;
- width = HLINES(8);
- height = HLINES(8);
- tex = TextureIterator({"assets/robin.png"});
- actCounterInitial = actCounter = 200;
-}
-
-void Bird::act(void)
-{
- static bool direction = false;
- static const float wstart = currentWorld->getWorldStart();
-
- if (!--actCounter) {
- actCounter = actCounterInitial;
- direction ^= 1;
- }
-
- if (loc.x > -wstart - HLINES(10.0f))
- loc.x = wstart + HLINES(10.0f);
- else if (loc.x < wstart + HLINES(10.0f))
- loc.x = -wstart - HLINES(10.0f);
-
- if (loc.y <= initialY)
- vel.y = 0.3f;
- vel.x = direction ? -0.3f : 0.3f;
-}
-
-void Bird::onHit(unsigned int _health)
-{
- takeHit(_health, 1000);
-}
-
-bool Bird::bindTex(void)
-{
- glActiveTexture(GL_TEXTURE0);
- tex(0);
- return true;
-}
-
-void Bird::createFromXML(XMLElement *e, World *w=nullptr)
-{
- (void)w;
- float Xlocx;
-
- xmle = e;
-
- if (e->QueryFloatAttribute("x", &Xlocx) == XML_NO_ERROR)
- loc.x = Xlocx;
- if (e->QueryFloatAttribute("y", &initialY) != XML_NO_ERROR)
- initialY = 300;
-
- E_LOAD_HEALTH;
-
- if (e->QueryBoolAttribute("aggressive", &aggressive) != XML_NO_ERROR)
- aggressive = false;
-}
-
-void Bird::saveToXML(void)
-{
- E_SAVE_COORDS;
- E_SAVE_HEALTH;
-}
-
-Trigger::Trigger(void) : Mob()
-{
- ridable = false;
- aggressive = false;
- maxHealth = health = 50;
- width = HLINES(20);
- height = 2000;
- //tex = TextureIterator();
- triggered = false;
- notext = false;
-}
-
-void Trigger::act(void)
-{
- auto c = player->loc.x + player->width / 2;
- static bool running = false;
-
- if (triggered) {
- die();
- } else if (!running && c > loc.x && c < loc.x + width) {
- std::thread([&]{
- running = true;
-
- XMLDocument xml;
- XMLElement *exml;
-
- xml.LoadFile(currentXML.c_str());
- exml = xml.FirstChildElement("Trigger");
-
- while(exml && exml->StrAttribute("id") != id)
- exml = exml->NextSiblingElement();
-
- player->vel.x = 0;
-
- if (notext) {
- for (auto &e : currentWorld->entity) {
- if (e->type == NPCT && e->name == exml->GetText()) {
- e->interact();
- break;
- }
- }
- } else {
-
- /*if (exml == nullptr) {
- auto id = xmle->StrAttribute("cid");
- if (!id.empty()) {
- game::setValue(id, xmle->StrAttribute("cvalue"));
- game::briceUpdate();
- }
- return;
- }*/
-
- ui::toggleBlackFast();
- ui::waitForCover();
-
- std::string text = exml->GetText();
- char *pch = strtok(&text[0], "\n");
-
- while (pch) {
- ui::importantText(pch);
- ui::waitForDialog();
- pch = strtok(NULL, "\n");
- }
-
- ui::toggleBlackFast();
- }
-
- triggered = true;
- running = false;
- }).detach();
- }
-}
-
-void Trigger::onHit(unsigned int _health)
-{
- (void)_health;
-}
-
-bool Trigger::bindTex(void)
-{
- return false;
-}
-
-void Trigger::createFromXML(XMLElement *e, World *w=nullptr)
-{
- (void)w;
- float Xlocx;
-
- if (e->QueryFloatAttribute("spawnx", &Xlocx) == XML_NO_ERROR)
- loc.x = Xlocx;
-
- if (e->QueryBoolAttribute("notext", ¬ext) != XML_NO_ERROR)
- notext = false;
-
- id = e->StrAttribute("id");
-
- xmle = e;
-}
-
-void Trigger::saveToXML(void)
-{}
-
-Chest::Chest(void) : Mob()
-{
- ridable = false;
- aggressive = false;
- maxHealth = health = 100;
- width = HLINES(10);
- height = HLINES(5);
- tex = TextureIterator({"assets/chest.png"});
- inv = new Inventory(1);
-}
-
-void Chest::act(void)
-{
- if (isInside(ui::mouse) && player->isNear(this)) {
- if ((SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_RIGHT)) && !ui::dialogBoxExists)
- for (auto &i : inv->Items) {
- player->inv->addItem(i.first->name, i.second);
- inv->takeItem(i.first->name, i.second);
- }
- }
-
- for (auto &e : currentWorld->entity) {
- if (e->type == OBJECTT && e->isNear(this)) {
- auto o = dynamic_cast<Object *>(e);
- inv->addItem(o->iname, 1);
- e->health = 0;
- }
- }
-}
-
-void Chest::onHit(unsigned int _health)
-{
- (void)_health;
- die();
-}
-
-bool Chest::bindTex(void)
-{
- glActiveTexture(GL_TEXTURE0);
- tex(0);
- return true;
-}
-
-void Chest::createFromXML(XMLElement *e, World *w)
-{
- (void)w;
- loc = vec2 { 0, 100 };
- xmle = e;
-}
-
-void Chest::saveToXML(void)
-{
- xmle->SetAttribute("alive", alive);
-}
-
-
-
-Mob::~Mob()
-{
- delete inv;
-}
-
-extern World *currentWorld;
-extern Arena *arena;
-
-void Mob::wander(void)
-{
- static bool YAYA = false;
-
- if (forcedMove)
- return;
-
- if (aggressive && !YAYA && isInside(vec2 {player->loc.x + width / 2, player->loc.y + height / 4})) {
- if (!ui::dialogBoxExists) {
- std::thread([&](void){
- arena->fight(currentWorld, player, this);
- ui::toggleWhiteFast();
- YAYA = true;
- ui::waitForCover();
- YAYA = false;
- currentWorld = arena;
- ui::toggleWhiteFast();
- }).detach();
- }
- }
- act();
-}
-
-void Mob::ride(Entity *e)
-{
- if (!ridable)
- return;
-
- if (rider == e)
- rider = nullptr;
- else
- rider = e;
-}
-
-void Mob::onDeath(void)
-{
- vec2 q = vec2 {player->loc.x, game::SCREEN_HEIGHT - 100.0f};
-
- ui::putTextL(q, "Player got: ");
-
- for (const auto &d : drop) {
- if ((randGet() % 100) < std::get<float>(d) * 100.0f) {
- q.y -= 20;
- ui::putTextL(q, "%d x %s", std::get<unsigned int>(d), std::get<std::string>(d).c_str());
- player->inv->addItem(std::get<std::string>(d), std::get<unsigned int>(d));
- }
- }
-}
--- /dev/null
+#include <mob.hpp>
+#include <ui.hpp>
+#include <world.hpp>
+#include <brice.hpp>
+
+extern World *currentWorld;
+
+Mob::Mob(void)
+{
+ type = MOBT;
+ inv = nullptr;
+ rider = nullptr;
+ xmle = nullptr;
+ canMove = true;
+ loc = 0;
+}
+
+Page::Page(void) : Mob()
+{
+
+ ridable = false;
+ aggressive = false;
+ maxHealth = health = 50;
+ width = HLINES(6);
+ height = HLINES(4);
+ tex = TextureIterator({"assets/items/ITEM_PAGE.png"});
+ pageTexture = 0;
+}
+
+void Page::act(void)
+{
+ if (player->loc.x > loc.x - 100 && player->loc.x < loc.x + 100 && isInside(ui::mouse) &&
+ (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_RIGHT))) {
+ std::thread([this](void){
+ ui::drawPage(pageTexture);
+ ui::waitForDialog();
+ game::setValue(cId, cValue);
+ game::briceUpdate();
+ die();
+ }).detach();
+ }
+}
+
+void Page::onHit(unsigned int _health)
+{
+ (void)_health;
+ act();
+}
+
+bool Page::bindTex(void)
+{
+ glActiveTexture(GL_TEXTURE0);
+ tex(0);
+ return true;
+}
+
+void Page::createFromXML(XMLElement *e, World *w=nullptr)
+{
+ (void)w;
+ float Xlocx;
+ if (e->QueryFloatAttribute("x", &Xlocx) == XML_NO_ERROR)
+ loc.x = Xlocx;
+ pageTexPath = e->StrAttribute("id");
+ pageTexture = Texture::loadTexture(pageTexPath);
+
+ cId = e->StrAttribute("cid");
+ cValue = e->StrAttribute("cvalue");
+
+ xmle = e;
+}
+
+void Page::saveToXML(void)
+{}
+
+Door::Door(void) : Mob()
+{
+ ridable = false;
+ aggressive = false;
+ maxHealth = health = 50;
+ width = HLINES(12);
+ height = HLINES(20);
+ tex = TextureIterator({"assets/style/classic/door.png"});
+}
+
+void Door::act(void)
+{
+}
+
+void Door::onHit(unsigned int _health)
+{
+ (void)_health;
+}
+
+bool Door::bindTex(void)
+{
+ glActiveTexture(GL_TEXTURE0);
+ tex(0);
+ return true;
+}
+
+void Door::createFromXML(XMLElement *e, World *w=nullptr)
+{
+ (void)w;
+ float Xlocx;
+ if (e->QueryFloatAttribute("x", &Xlocx) == XML_NO_ERROR)
+ loc.x = Xlocx;
+}
+
+void Door::saveToXML(void)
+{}
+
+Cat::Cat(void) : Mob()
+{
+ ridable = true;
+ aggressive = false;
+ maxHealth = health = 100000;
+ width = HLINES(19);
+ height = HLINES(15);
+ tex = TextureIterator({"assets/cat.png"});
+ actCounterInitial = 0;
+ actCounter = 1;
+}
+
+void Cat::act(void)
+{
+ static float vely = 0;
+ if (rider != nullptr) {
+ if (!rider->ground) {
+ loc.y += HLINES(2);
+ vel.y = .4;
+ }
+ if (rider->speed > 1) {
+ vely = .5;
+ } else if (rider->speed == .5) {
+ vely = -.5;
+ } else {
+ vely = 0;
+ }
+ vel.y = vely;
+ if (!rider->ground) {
+ if ((vel.y -= .015) < -.2)
+ rider->ground = true;
+ }
+ vel.x = .1 * (rider->left ? -1 : 1);
+ } else {
+ vel = 0;
+ }
+}
+
+void Cat::onHit(unsigned int _health)
+{
+ health += _health;
+}
+
+bool Cat::bindTex(void)
+{
+ glActiveTexture(GL_TEXTURE0);
+ tex(0);
+ return true;
+}
+
+void Cat::createFromXML(XMLElement *e, World *w=nullptr)
+{
+ (void)w;
+ float spawnc;
+
+ if (e->QueryFloatAttribute("x", &spawnc) == XML_NO_ERROR)
+ loc.x = spawnc;
+ else
+ loc.x = e->FloatAttribute("spawnx");
+
+ if (e->QueryFloatAttribute("y", &spawnc) == XML_NO_ERROR)
+ loc.y = spawnc;
+
+ xmle = e;
+}
+
+void Cat::saveToXML(void)
+{
+ E_SAVE_COORDS;
+ xmle->SetAttribute("alive", alive);
+}
+
+Rabbit::Rabbit(void) : Mob()
+{
+ ridable = true;
+ aggressive = false;
+ maxHealth = health = 50;
+ width = HLINES(10);
+ height = HLINES(8);
+ tex = TextureIterator({"assets/rabbit.png", "assets/rabbit1.png"});
+ actCounterInitial = randGet() % 240 + 15;
+ actCounter = 1;
+
+ drop = {
+ std::make_tuple("Dank MayMay", 5, 1.00f)
+ };
+}
+
+void Rabbit::act(void)
+{
+ static int direction = 0;
+
+ if (!--actCounter) {
+ actCounter = actCounterInitial;
+ direction = (randGet() % 3 - 1); //sets the direction to either -1, 0, 1
+ if (direction == 0)
+ ticksToUse /= 2;
+ vel.x *= direction;
+ }
+
+ if (ground && direction) {
+ ground = false;
+ vel.y = .15;
+ loc.y += HLINES(0.25f);
+ vel.x = 0.05f * direction;
+ }
+}
+
+void Rabbit::onHit(unsigned int _health)
+{
+ takeHit(_health, 600);
+}
+
+bool Rabbit::bindTex(void)
+{
+ glActiveTexture(GL_TEXTURE0);
+ tex(!ground);
+ return true;
+}
+
+void Rabbit::createFromXML(XMLElement *e, World *w=nullptr)
+{
+ (void)w;
+ float spawnc;
+
+ xmle = e;
+
+ if (e->QueryFloatAttribute("x", &spawnc) == XML_NO_ERROR)
+ loc.x = spawnc;
+ else
+ loc.x = e->FloatAttribute("spawnx");
+
+ if (e->QueryFloatAttribute("y", &spawnc) == XML_NO_ERROR)
+ loc.y = spawnc;
+
+ E_LOAD_HEALTH;
+
+ if (e->QueryBoolAttribute("aggressive", &aggressive) != XML_NO_ERROR)
+ aggressive = false;
+}
+
+void Rabbit::saveToXML(void)
+{
+ E_SAVE_HEALTH;
+}
+
+Bird::Bird(void) : Mob()
+{
+ ridable = true;
+ aggressive = false;
+ maxHealth = health = 50;
+ width = HLINES(8);
+ height = HLINES(8);
+ tex = TextureIterator({"assets/robin.png"});
+ actCounterInitial = actCounter = 200;
+}
+
+void Bird::act(void)
+{
+ static bool direction = false;
+ static const float wstart = currentWorld->getWorldStart();
+
+ if (!--actCounter) {
+ actCounter = actCounterInitial;
+ direction ^= 1;
+ }
+
+ if (loc.x > -wstart - HLINES(10.0f))
+ loc.x = wstart + HLINES(10.0f);
+ else if (loc.x < wstart + HLINES(10.0f))
+ loc.x = -wstart - HLINES(10.0f);
+
+ if (loc.y <= initialY)
+ vel.y = 0.3f;
+ vel.x = direction ? -0.3f : 0.3f;
+}
+
+void Bird::onHit(unsigned int _health)
+{
+ takeHit(_health, 1000);
+}
+
+bool Bird::bindTex(void)
+{
+ glActiveTexture(GL_TEXTURE0);
+ tex(0);
+ return true;
+}
+
+void Bird::createFromXML(XMLElement *e, World *w=nullptr)
+{
+ (void)w;
+ float Xlocx;
+
+ xmle = e;
+
+ if (e->QueryFloatAttribute("x", &Xlocx) == XML_NO_ERROR)
+ loc.x = Xlocx;
+ if (e->QueryFloatAttribute("y", &initialY) != XML_NO_ERROR)
+ initialY = 300;
+
+ E_LOAD_HEALTH;
+
+ if (e->QueryBoolAttribute("aggressive", &aggressive) != XML_NO_ERROR)
+ aggressive = false;
+}
+
+void Bird::saveToXML(void)
+{
+ E_SAVE_COORDS;
+ E_SAVE_HEALTH;
+}
+
+Trigger::Trigger(void) : Mob()
+{
+ ridable = false;
+ aggressive = false;
+ maxHealth = health = 50;
+ width = HLINES(20);
+ height = 2000;
+ //tex = TextureIterator();
+ triggered = false;
+ notext = false;
+}
+
+void Trigger::act(void)
+{
+ auto c = player->loc.x + player->width / 2;
+ static bool running = false;
+
+ if (triggered) {
+ die();
+ } else if (!running && c > loc.x && c < loc.x + width) {
+ std::thread([&]{
+ running = true;
+
+ XMLDocument xml;
+ XMLElement *exml;
+
+ xml.LoadFile(currentXML.c_str());
+ exml = xml.FirstChildElement("Trigger");
+
+ while(exml && exml->StrAttribute("id") != id)
+ exml = exml->NextSiblingElement();
+
+ player->vel.x = 0;
+
+ if (notext) {
+ for (auto &e : currentWorld->entity) {
+ if (e->type == NPCT && e->name == exml->GetText()) {
+ e->interact();
+ break;
+ }
+ }
+ } else {
+
+ /*if (exml == nullptr) {
+ auto id = xmle->StrAttribute("cid");
+ if (!id.empty()) {
+ game::setValue(id, xmle->StrAttribute("cvalue"));
+ game::briceUpdate();
+ }
+ return;
+ }*/
+
+ ui::toggleBlackFast();
+ ui::waitForCover();
+
+ std::string text = exml->GetText();
+ char *pch = strtok(&text[0], "\n");
+
+ while (pch) {
+ ui::importantText(pch);
+ ui::waitForDialog();
+ pch = strtok(NULL, "\n");
+ }
+
+ ui::toggleBlackFast();
+ }
+
+ triggered = true;
+ running = false;
+ }).detach();
+ }
+}
+
+void Trigger::onHit(unsigned int _health)
+{
+ (void)_health;
+}
+
+bool Trigger::bindTex(void)
+{
+ return false;
+}
+
+void Trigger::createFromXML(XMLElement *e, World *w=nullptr)
+{
+ (void)w;
+ float Xlocx;
+
+ if (e->QueryFloatAttribute("spawnx", &Xlocx) == XML_NO_ERROR)
+ loc.x = Xlocx;
+
+ if (e->QueryBoolAttribute("notext", ¬ext) != XML_NO_ERROR)
+ notext = false;
+
+ id = e->StrAttribute("id");
+
+ xmle = e;
+}
+
+void Trigger::saveToXML(void)
+{}
+
+Chest::Chest(void) : Mob()
+{
+ ridable = false;
+ aggressive = false;
+ maxHealth = health = 100;
+ width = HLINES(10);
+ height = HLINES(5);
+ tex = TextureIterator({"assets/chest.png"});
+ inv = new Inventory(1);
+}
+
+void Chest::act(void)
+{
+ if (isInside(ui::mouse) && player->isNear(this)) {
+ if ((SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_RIGHT)) && !ui::dialogBoxExists)
+ for (auto &i : inv->Items) {
+ player->inv->addItem(i.first->name, i.second);
+ inv->takeItem(i.first->name, i.second);
+ }
+ }
+
+ for (auto &e : currentWorld->entity) {
+ if (e->type == OBJECTT && e->isNear(this)) {
+ auto o = dynamic_cast<Object *>(e);
+ inv->addItem(o->iname, 1);
+ e->health = 0;
+ }
+ }
+}
+
+void Chest::onHit(unsigned int _health)
+{
+ (void)_health;
+ die();
+}
+
+bool Chest::bindTex(void)
+{
+ glActiveTexture(GL_TEXTURE0);
+ tex(0);
+ return true;
+}
+
+void Chest::createFromXML(XMLElement *e, World *w)
+{
+ (void)w;
+ loc = vec2 { 0, 100 };
+ xmle = e;
+}
+
+void Chest::saveToXML(void)
+{
+ xmle->SetAttribute("alive", alive);
+}
+
+
+
+Mob::~Mob()
+{
+ delete inv;
+}
+
+extern World *currentWorld;
+extern Arena *arena;
+
+void Mob::wander(void)
+{
+ static bool YAYA = false;
+
+ if (forcedMove)
+ return;
+
+ if (aggressive && !YAYA && isInside(vec2 {player->loc.x + width / 2, player->loc.y + height / 4})) {
+ if (!ui::dialogBoxExists) {
+ std::thread([&](void){
+ arena->fight(currentWorld, player, this);
+ ui::toggleWhiteFast();
+ YAYA = true;
+ ui::waitForCover();
+ YAYA = false;
+ currentWorld = arena;
+ ui::toggleWhiteFast();
+ }).detach();
+ }
+ }
+ act();
+}
+
+void Mob::ride(Entity *e)
+{
+ if (!ridable)
+ return;
+
+ if (rider == e)
+ rider = nullptr;
+ else
+ rider = e;
+}
+
+void Mob::onDeath(void)
+{
+ vec2 q = vec2 {player->loc.x, game::SCREEN_HEIGHT - 100.0f};
+
+ ui::putTextL(q, "Player got: ");
+
+ for (const auto &d : drop) {
+ if ((randGet() % 100) < std::get<float>(d) * 100.0f) {
+ q.y -= 20;
+ ui::putTextL(q, "%d x %s", std::get<unsigned int>(d), std::get<std::string>(d).c_str());
+ player->inv->addItem(std::get<std::string>(d), std::get<unsigned int>(d));
+ }
+ }
+}
+++ /dev/null
-#include <algorithm>\r
-\r
-#include <quest.hpp>\r
-#include <entities.hpp>\r
-\r
-extern Player *player;\r
-\r
-int QuestHandler::assign(std::string title,std::string desc,std::string req) {\r
- Quest tmp;\r
- char *tok;\r
-\r
- tmp.title = title;\r
- tmp.desc = desc;\r
-\r
- tok = strtok(&req[0], "\n\r\t,");\r
- tmp.need.emplace_back("", 0);\r
-\r
- while (tok) {\r
- if (!tmp.need.back().first.empty()) {\r
- tmp.need.back().second = atoi(tok);\r
- tmp.need.emplace_back("", 0);\r
- } else\r
- tmp.need.back().first = tok;\r
-\r
- tok = strtok(NULL, "\n\r\t,");\r
- }\r
-\r
- tmp.need.pop_back();\r
- current.push_back(tmp);\r
-\r
- return 0;\r
-}\r
-\r
-int QuestHandler::drop(std::string title) {\r
- current.erase(std::remove_if (current.begin(),\r
- current.end(),\r
- [&](Quest q) { return q.title == title; }),\r
- current.end());\r
-\r
- return 0;\r
-}\r
-\r
-int QuestHandler::finish(std::string t) {\r
- for (auto c = current.begin(); c != current.end(); c++) {\r
- if ((*c).title == t) {\r
- for (auto &n : (*c).need) {\r
- if (player->inv->hasItem(n.first) < n.second)\r
- return 0;\r
- }\r
-\r
- for (auto &n : (*c).need)\r
- player->inv->takeItem(n.first, n.second);\r
- current.erase(c);\r
- return 1;\r
- }\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-bool QuestHandler::hasQuest(std::string t) {\r
- for (auto &c : current) {\r
- if (c.title == t)\r
- return true;\r
- }\r
-\r
- return false;\r
-}\r
--- /dev/null
+#include <algorithm>\r
+\r
+#include <quest.hpp>\r
+\r
+int QuestHandler::assign(std::string title,std::string desc,std::string req) {\r
+ Quest tmp;\r
+ char *tok;\r
+\r
+ tmp.title = title;\r
+ tmp.desc = desc;\r
+\r
+ tok = strtok(&req[0], "\n\r\t,");\r
+ tmp.need.emplace_back("", 0);\r
+\r
+ while (tok) {\r
+ if (!tmp.need.back().first.empty()) {\r
+ tmp.need.back().second = atoi(tok);\r
+ tmp.need.emplace_back("", 0);\r
+ } else\r
+ tmp.need.back().first = tok;\r
+\r
+ tok = strtok(NULL, "\n\r\t,");\r
+ }\r
+\r
+ tmp.need.pop_back();\r
+ current.push_back(tmp);\r
+\r
+ return 0;\r
+}\r
+\r
+int QuestHandler::drop(std::string title) {\r
+ current.erase(std::remove_if (current.begin(),\r
+ current.end(),\r
+ [&](Quest q) { return q.title == title; }),\r
+ current.end());\r
+\r
+ return 0;\r
+}\r
+\r
+int QuestHandler::finish(std::string t) {\r
+ for (auto c = current.begin(); c != current.end(); c++) {\r
+ if ((*c).title == t) {\r
+ //for (auto &n : (*c).need) {\r
+ //if (player->inv->hasItem(n.first) < n.second)\r
+ return 0;\r
+ //}\r
+\r
+ //for (auto &n : (*c).need)\r
+ //player->inv->takeItem(n.first, n.second);\r
+ //current.erase(c);\r
+ //return 1;\r
+ }\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+bool QuestHandler::hasQuest(std::string t) {\r
+ for (auto &c : current) {\r
+ if (c.title == t)\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+}\r
extern SDL_Window *window;
-/**
- * External references for updating player coords / current world.
- */
-
-extern Player *player;
-extern World *currentWorld;
-extern World *currentWorldToLeft;
-extern World *currentWorldToRight;
-
-/**
- * Pressing ESC or closing the window will set this to false.
- */
-extern bool gameRunning;
-
-
std::array<SDL_Keycode, 6> controlMap = {
SDLK_w, SDLK_a, SDLK_d, SDLK_LSHIFT, SDLK_LCTRL, SDLK_e
};
static std::vector<std::pair<std::string,vec3>> dialogOptText;
static std::string dialogBoxText;
-static std::vector<vec3> merchArrowLoc (2, vec3 { 0, 0, 0 });
static bool typeOutDone = true;
static bool typeOutSustain = false;
bool dialogPassive = false;
bool dialogMerchant = false;
int dialogPassiveTime = 0;
- Trade merchTrade;
int fontTransInv = 255;
bool dialogBoxExists = false;
bool dialogImportant = false;
unsigned char dialogOptChosen = 0;
- unsigned char merchOptChosen = 0;
unsigned int textWrapLimit = 0;
ret.clear();
}
- void merchantBox(const char *name,Trade trade,const char *opt,bool passive,const char *text,...) {
- va_list dialogArgs;
- std::unique_ptr<char[]> printfbuf (new char[512]);
-
- dialogPassive = passive;
- merchTrade = trade;
-
- // clear the buffer
- dialogBoxText.clear();
- dialogBoxText = (std::string)name + ": ";
-
- va_start(dialogArgs,text);
- vsnprintf(printfbuf.get(),512,text,dialogArgs);
- va_end(dialogArgs);
- dialogBoxText += printfbuf.get();
-
- // free old option text
- dialogOptText.clear();
-
- dialogOptChosen = 0;
- merchOptChosen = 0;
-
- // handle options if desired
- if (opt) {
- std::string soptbuf = opt;
- char *sopt = strtok(&soptbuf[0], ":");
-
- // cycle through options
- while(sopt) {
- dialogOptText.push_back(std::make_pair((std::string)sopt, vec3 {0,0,0}));
- sopt = strtok(NULL,":");
- }
- }
-
- // allow box to be displayed
- dialogBoxExists = true;
- dialogImportant = false;
- dialogMerchant = true;
- textWrapLimit = 50;
-
- ret.clear();
- }
-
- void merchantBox() {
- textWrapLimit = 50;
- dialogMerchant = true;
- }
-
/**
* Wait for a dialog box to be dismissed.
*/
auto SCREEN_HEIGHT = static_cast<float>(game::SCREEN_HEIGHT);
// will return if not toggled
- action::draw(vec2 {player->loc.x + player->width / 2, player->loc.y + player->height + game::HLINE});
+ //action::draw(vec2 {player->loc.x + player->width / 2, player->loc.y + player->height + game::HLINE});
// will return if not toggled
quest::draw();
putStringCentered(offset.x,offset.y,rtext);
setFontSize(16);
}
- }else if (dialogMerchant) {
- x = offset.x - SCREEN_WIDTH / 6;
- y = (offset.y + SCREEN_HEIGHT / 2) - HLINES(8);
-
- drawNiceBox(vec2(x, y), vec2(x + (SCREEN_WIDTH / 3.0f), y - (SCREEN_HEIGHT * 0.6f)), -7.0f);
- // draw typeOut'd text
- putString(x + game::HLINE, y - fontSize - game::HLINE, (rtext = typeOut(dialogBoxText)));
-
- std::string itemString1 = std::to_string(merchTrade.quantity[0]) + "x",
- itemString2 = std::to_string(merchTrade.quantity[1]) + "x";
-
- vec2 merchBase = {offset.x, offset.y + SCREEN_HEIGHT / 5};
-
- putStringCentered(merchBase.x + SCREEN_WIDTH / 10 - 20, merchBase.y + 40 + fontSize * 2, itemString1);
- putStringCentered(merchBase.x + SCREEN_WIDTH / 10 - 20, merchBase.y + 40 + fontSize , merchTrade.item[0]);
- putStringCentered(merchBase.x - SCREEN_WIDTH / 10 , merchBase.y + 40 + fontSize * 2, itemString2);
- putStringCentered(merchBase.x - SCREEN_WIDTH / 10 , merchBase.y + 40 + fontSize , merchTrade.item[1]);
- putStringCentered(offset.x, merchBase.y + 60, "for");
-
- // render the two items we are trading
- GLfloat item_tex[] = {0.0, 1.0,
- 1.0, 1.0,
- 1.0, 0.0,
-
- 1.0, 0.0,
- 0.0, 0.0,
- 0.0, 1.0};
-
- GLfloat left_item[] = {offset.x - (SCREEN_WIDTH / 10), offset.y + (SCREEN_HEIGHT / 5), -7.2,
- offset.x - (SCREEN_WIDTH / 10) + 40, offset.y + (SCREEN_HEIGHT / 5), -7.2,
- offset.x - (SCREEN_WIDTH / 10) + 40, offset.y + (SCREEN_HEIGHT / 5) + 40,-7.2,
-
- offset.x - (SCREEN_WIDTH / 10) + 40, offset.y + (SCREEN_HEIGHT / 5) + 40,-7.2,
- offset.x - (SCREEN_WIDTH / 10), offset.y + (SCREEN_HEIGHT / 5) + 40,-7.2,
- offset.x - (SCREEN_WIDTH / 10), offset.y + (SCREEN_HEIGHT / 5), -7.2};
-
- GLfloat right_item[] = {offset.x + (SCREEN_WIDTH / 10) - 40, offset.y + (SCREEN_HEIGHT / 5), -7.2,
- offset.x + (SCREEN_WIDTH / 10), offset.y + (SCREEN_HEIGHT / 5), -7.2,
- offset.x + (SCREEN_WIDTH / 10), offset.y + (SCREEN_HEIGHT / 5) + 40,-7.2,
-
- offset.x + (SCREEN_WIDTH / 10), offset.y + (SCREEN_HEIGHT / 5) + 40,-7.2,
- offset.x + (SCREEN_WIDTH / 10) - 40, offset.y + (SCREEN_HEIGHT / 5) + 40,-7.2,
- offset.x + (SCREEN_WIDTH / 10) - 40, offset.y + (SCREEN_HEIGHT / 5), -7.2};
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, getItemTexture(merchTrade.item[1]));
- glUniform1i(Render::textShader.uniform[WU_texture], 0);
-
- Render::textShader.use();
- Render::textShader.enable();
-
- glVertexAttribPointer(Render::textShader.coord, 3, GL_FLOAT, GL_FALSE, 0, left_item);
- glVertexAttribPointer(Render::textShader.tex, 2, GL_FLOAT, GL_FALSE, 0, item_tex);
- glDrawArrays(GL_TRIANGLES, 0 ,6);
-
- glBindTexture(GL_TEXTURE_2D, getItemTexture(merchTrade.item[0]));
-
- glVertexAttribPointer(Render::textShader.coord, 3, GL_FLOAT, GL_FALSE, 0, right_item);
- glVertexAttribPointer(Render::textShader.tex, 2, GL_FLOAT, GL_FALSE, 0, item_tex);
- glDrawArrays(GL_TRIANGLES, 0 ,6);
-
- Render::textShader.disable();
- Render::textShader.unuse();
-
- merchArrowLoc[0].x = offset.x - (SCREEN_WIDTH / 8.5) - 16;
- merchArrowLoc[1].x = offset.x + (SCREEN_WIDTH / 8.5) + 16;
- merchArrowLoc[0].y = offset.y + (SCREEN_HEIGHT *.2);
- merchArrowLoc[1].y = offset.y + (SCREEN_HEIGHT *.2);
- merchArrowLoc[0].z = offset.x - (SCREEN_WIDTH / 8.5);
- merchArrowLoc[1].z = offset.x + (SCREEN_WIDTH / 8.5);
-
- for(i = 0; i < 2; i++) {
- if (((merchArrowLoc[i].x < merchArrowLoc[i].z) ?
- (mouse.x > merchArrowLoc[i].x && mouse.x < merchArrowLoc[i].z) :
- (mouse.x < merchArrowLoc[i].x && mouse.x > merchArrowLoc[i].z)) &&
- mouse.y > merchArrowLoc[i].y - 8 && mouse.y < merchArrowLoc[i].y + 8) {
- glColor3ub(255,255, 0);
- glBindTexture(GL_TEXTURE_2D, Texture::genColor(Color(255,255,0)));
- }else{
- glColor3ub(255,255,255);
- glBindTexture(GL_TEXTURE_2D, Texture::genColor(Color(255,255,255)));
- }
-
- GLfloat tri_t[] = {0.0, 0.0,
- 0.0, 1.0,
- 1.0, 1.0};
-
- GLfloat tri_c[] = {merchArrowLoc[i].x, merchArrowLoc[i].y, -7.1,
- merchArrowLoc[i].z, merchArrowLoc[i].y - 8, -7.1,
- merchArrowLoc[i].z, merchArrowLoc[i].y + 8, -7.1};
-
- glUniform1i(Render::textShader.uniform[WU_texture], 0);
-
- Render::textShader.use();
- Render::textShader.enable();
-
- glVertexAttribPointer(Render::textShader.coord, 3, GL_FLOAT, GL_FALSE, 0, tri_c);
- glVertexAttribPointer(Render::textShader.tex, 2, GL_FLOAT, GL_FALSE, 0, tri_t);
- glDrawArrays(GL_TRIANGLES, 0 ,6);
-
- Render::textShader.disable();
- Render::textShader.unuse();
- }
-
-
- // draw / handle dialog options if they exist
- for(i = 0; i < dialogOptText.size(); i++) {
- setFontColor(255, 255, 255);
-
- // draw option
- dialogOptText[i].second.y = y - SCREEN_HEIGHT / 2 - (fontSize + game::HLINE) * (i + 1);
- tmp = putStringCentered(offset.x, dialogOptText[i].second.y, dialogOptText[i].first);
-
- // get coordinate information on option
- dialogOptText[i].second.z = offset.x + tmp;
- dialogOptText[i].second.x = offset.x - tmp;
-
- // make text yellow if the mouse hovers over the text
- if (mouse.x > dialogOptText[i].second.x && mouse.x < dialogOptText[i].second.z &&
- mouse.y > dialogOptText[i].second.y && mouse.y < dialogOptText[i].second.y + 16) {
- setFontColor(255, 255, 0);
- putStringCentered(offset.x, dialogOptText[i].second.y, dialogOptText[i].first);
- }
- }
-
- setFontColor(255, 255, 255);
} else { //normal dialog box
x = offset.x - SCREEN_WIDTH / 2 + HLINES(8);
}
if (!fadeIntensity) {
- vec2 hub = {
+ /*vec2 hub = {
(SCREEN_WIDTH/2+offset.x)-fontSize*10,
(offset.y+SCREEN_HEIGHT/2)-fontSize
- };
+ };*/
- putText(hub.x,hub.y,"Health: %u/%u",player->health>0?(unsigned)player->health:0,
+ /*putText(hub.x,hub.y,"Health: %u/%u",player->health>0?(unsigned)player->health:0,
(unsigned)player->maxHealth
- );
- static GLuint frontHealth = Texture::genColor(Color(255,0,0));
+ );*/
+ /*static GLuint frontHealth = Texture::genColor(Color(255,0,0));
static GLuint backHealth = Texture::genColor(Color(150,0,0));
if (player->isAlive()) {
Render::textShader.disable();
Render::textShader.unuse();
- }
+ }*/
/*
* Lists all of the quests the player is currently taking.
*/
- setFontColor(255,255,255,fontTransInv);
+ /*setFontColor(255,255,255,fontTransInv);
if (player->inv->invOpen) {
hub.y = player->loc.y + fontSize * 8;
hub.x = player->loc.x;// + player->width / 2;
hub.x = offset.x - SCREEN_WIDTH/2 + 45*4*1.5;
putStringCentered(hub.x,hub.y,"Inventory:");
- }
+ }*/
setFontColor(255,255,255,255);
}
}
}
}
- if (dialogMerchant) {
- for (i = 0; i < merchArrowLoc.size(); i++) {
-
- // TODO neaten this if statement
-
- if (((merchArrowLoc[i].x < merchArrowLoc[i].z) ?
- (mouse.x > merchArrowLoc[i].x && mouse.x < merchArrowLoc[i].z) :
- (mouse.x < merchArrowLoc[i].x && mouse.x > merchArrowLoc[i].z) &&
- mouse.y > merchArrowLoc[i].y - 8 && mouse.y < merchArrowLoc[i].y + 8)) {
- merchOptChosen = i + 1;
- goto EXIT;
- }
- }
- }
-
-
EXIT:
- //if (!dialogMerchant)closeBox();
dialogBoxExists = false;
- dialogMerchant = false;
// handle important text
if (dialogImportant) {
auto SCREEN_WIDTH = game::SCREEN_WIDTH;
auto SCREEN_HEIGHT = game::SCREEN_HEIGHT;
- Mob *m; // ;lkjfdsa
- Entity *ent; // used for interaction
-
SDL_Event e;
// update mouse coords
mouse.x = premouse.x + offset.x - (SCREEN_WIDTH / 2);
mouse.y = (offset.y + SCREEN_HEIGHT / 2) - premouse.y;
- static vec2 fr;
- static Entity *ig;
-
while(SDL_PollEvent(&e)) {
switch(e.type) {
premouse.y=e.motion.y;
break;
- case SDL_MOUSEBUTTONUP:
- if (ig) {
- ig->vel.x = (fr.x - mouse.x) / 50.0f;
- ig->vel.y = (fr.y - mouse.y) / 50.0f;
- //ig->forcedMove = true; // kills vel.x too quickly
- ig = NULL;
- }
- break;
+ //case SDL_MOUSEBUTTONUP:
- // mouse clicks
case SDL_MOUSEBUTTONDOWN:
// run actions?
- if ((action::make = e.button.button & SDL_BUTTON_RIGHT))
- /*player->inv->invHover =*/ edown = false;
+ //if ((action::make = e.button.button & SDL_BUTTON_RIGHT))
+ // /*player->inv->invHover =*/ edown = false;
textToDraw.clear();
} else {
// left click uses item
if (e.button.button & SDL_BUTTON_LEFT) {
- if ((ent = currentWorld->getNearMob(*player)) != nullptr) {
+ /*if ((ent = currentWorld->getNearMob(*player)) != nullptr) {
player->inv->currentAddInteract(ent);
}
- player->inv->useCurrent();
+ player->inv->useCurrent();*/
}
}
-
- if(mouse.x > player->loc.x && mouse.x < player->loc.x + player->width &&
- mouse.y > player->loc.y && mouse.y < player->loc.y + player->height) {
- player->vel.y = .05;
- fr = mouse;
- ig = player;
- } else {
- for (auto &e : currentWorld->entity) {
- if (mouse.x > e->loc.x && mouse.x < e->loc.x + e->width &&
- mouse.y > e->loc.y && mouse.y < e->loc.y + e->height) {
- e->vel.y = .05;
- fr = mouse;
- ig = e;
- break;
- }
- }
- }
-
break;
case SDL_MOUSEWHEEL:
case SDL_KEYUP:
ev.emit<KeyUpEvent>(SDL_KEY);
+ if (SDL_KEY == SDLK_ESCAPE)
+ ui::menu::toggle();
+
if (SDL_KEY == SDLK_q) {
- auto item = player->inv->getCurrentItem();
+ /*auto item = player->inv->getCurrentItem();
if (item != nullptr) {
if (player->inv->takeItem(item->name, 1) == 0)
currentWorld->addObject(item->name, "o shit waddup",
player->loc.x + player->width / 2, player->loc.y + player->height / 2);
- }
+ }*/
} else if (SDL_KEY == SDLK_h) {
quest::toggle();
} else switch (SDL_KEY) {
case SDLK_BACKSLASH:
dialogBoxExists = false;
break;
- case SDLK_x:
- m = currentWorld->getNearMob(*player);
- if (m != nullptr)
- m->ride(player);
- break;
- case SDLK_l:
- currentWorld->addLight({player->loc.x + SCREEN_WIDTH/2, player->loc.y}, 300.0f, {1.0f,1.0f,1.0f});
- currentWorld->getLastLight().follow(player);
- currentWorld->getLastLight().makeFlame();
- break;
- case SDLK_f:
- currentWorld->addLight({player->loc.x, player->loc.y}, 300.0f, {1.0f,1.0f,1.0f});
- break;
case SDLK_b:
if (debug)
posFlag ^= true;
- else {
- 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();
- }
+
break;
case SDLK_F12:
// Make the BYTE array, factor of 3 because it's RBG.
std::cout << "Took screenshot" << std::endl;
break;
case SDLK_UP:
- player->inv->setSelectionUp();
+ //player->inv->setSelectionUp();
break;
case SDLK_DOWN:
- player->inv->setSelectionDown();
+ //player->inv->setSelectionDown();
break;
default:
break;
+++ /dev/null
-#include <ui_action.hpp>
-#include <world.hpp>
-
-#define ACTION_PROLOUGE { actioning = true; }
-#define ACTION_EPILOUGE { actioning = false; actionHover = 0; }
-
-extern World *currentWorld;
-extern Arena *arena;
-extern Player *player;
-extern bool inBattle;
-
-static std::vector<std::pair<std::string, vec3>> actionText = {
- {"Attack", vec3 {0, 0, 0}},
- {"Action", vec3 {0, 0, 0}},
- {"Umm" , vec3 {0, 0, 0}}
-};
-
-void actionAttack(void);
-void actionAction(void);
-
-static std::vector<void (*)(void)> actionFunc = {
- actionAttack,
- actionAction,
- nullptr,
-};
-
-static bool actionToggle = false, actioning = false;
-static unsigned int actionHover = 0;
-static Entity *nearEntity = nullptr, *lastEntity = nullptr;
-
-namespace ui {
- namespace action {
- bool make = false;
-
- // enables action ui
- void enable(void) {
- actionToggle = true;
- }
-
- // disables action ui
- void disable(void) {
- actionToggle = false;
-
- if (lastEntity != nullptr)
- lastEntity->canMove = true;
- }
-
- // draws the action ui
- void draw(vec2 loc) {
- unsigned int i = 1;
- float y = loc.y;
-
- if (!actionToggle)
- return;
-
- nearEntity = currentWorld->getNearInteractable(*player);
-
- if (nearEntity == nullptr) {
- if (lastEntity != nullptr) {
- lastEntity->canMove = true;
- lastEntity = nullptr;
- }
- return;
- } else if (nearEntity != lastEntity) {
- if (lastEntity != nullptr)
- lastEntity->canMove = true;
- lastEntity = nearEntity;
- }
-
- if (make) {
- while(actioning);
-
- if (!actionHover) {
- make = false;
- return;
- }
-
- if (actionFunc[actionHover - 1] != nullptr)
- std::thread(actionFunc[actionHover - 1]).detach();
-
- actionHover = 0;
- } else {
- nearEntity->canMove = false;
- ui::drawBox(vec2 {loc.x - HLINES(11), loc.y}, vec2 {loc.x + HLINES(12), loc.y + actionText.size() * HLINES(8)});
-
- for (auto &s : actionText) {
- s.second.z = ui::putStringCentered((s.second.x = loc.x), (s.second.y = (y += fontSize * 1.15f)), s.first) / 2;
-
- if (ui::mouse.x > s.second.x - s.second.z && ui::mouse.x < s.second.x + s.second.z &&
- ui::mouse.y > s.second.y && ui::mouse.y < s.second.y + ui::fontSize) {
- actionHover = i;
- ui::setFontColor(255, 100, 100, 255);
- ui::putStringCentered(s.second.x, s.second.y, s.first);
- ui::setFontColor(255, 255, 255, 255);
- }
- i++;
- }
-
- ui::putStringCentered(loc.x, y + fontSize * 1.2f, nearEntity->name);
- }
-
- if (i == actionText.size())
- actionHover = 0;
-
- ui::setFontColor(255, 255, 255, 255);
- make = false;
- }
- }
-}
-
-void actionAttack(void)
-{
- ACTION_PROLOUGE;
-
- auto m = currentWorld->getNearInteractable(*player);
-
- if (m->type == MOBT) {
- if (!inBattle && m != nullptr) {
- arena->fight(currentWorld, player, Mobp(m));
-
- ui::toggleWhiteFast();
- ui::waitForCover();
- currentWorld = arena;
- ui::toggleWhiteFast();
- }
- } else {
- ui::dialogBox(player->name, "", false, "%s doesn't appear to be in the mood for fighting...", m->name.c_str());
- }
-
- ACTION_EPILOUGE;
-}
-
-void actionAction(void)
-{
- ACTION_PROLOUGE;
-
- auto e = currentWorld->getNearInteractable(*player);
-
- if (e->type == NPCT)
- e->interact();
-
- ACTION_EPILOUGE;
-}
--- /dev/null
+#include <ui_action.hpp>
+#include <world.hpp>
+
+#define ACTION_PROLOUGE { actioning = true; }
+#define ACTION_EPILOUGE { actioning = false; actionHover = 0; }
+
+extern World *currentWorld;
+extern Arena *arena;
+extern Player *player;
+extern bool inBattle;
+
+static std::vector<std::pair<std::string, vec3>> actionText = {
+ {"Attack", vec3 {0, 0, 0}},
+ {"Action", vec3 {0, 0, 0}},
+ {"Umm" , vec3 {0, 0, 0}}
+};
+
+void actionAttack(void);
+void actionAction(void);
+
+static std::vector<void (*)(void)> actionFunc = {
+ actionAttack,
+ actionAction,
+ nullptr,
+};
+
+static bool actionToggle = false, actioning = false;
+static unsigned int actionHover = 0;
+static Entity *nearEntity = nullptr, *lastEntity = nullptr;
+
+namespace ui {
+ namespace action {
+ bool make = false;
+
+ // enables action ui
+ void enable(void) {
+ actionToggle = true;
+ }
+
+ // disables action ui
+ void disable(void) {
+ actionToggle = false;
+
+ if (lastEntity != nullptr)
+ lastEntity->canMove = true;
+ }
+
+ // draws the action ui
+ void draw(vec2 loc) {
+ unsigned int i = 1;
+ float y = loc.y;
+
+ if (!actionToggle)
+ return;
+
+ nearEntity = currentWorld->getNearInteractable(*player);
+
+ if (nearEntity == nullptr) {
+ if (lastEntity != nullptr) {
+ lastEntity->canMove = true;
+ lastEntity = nullptr;
+ }
+ return;
+ } else if (nearEntity != lastEntity) {
+ if (lastEntity != nullptr)
+ lastEntity->canMove = true;
+ lastEntity = nearEntity;
+ }
+
+ if (make) {
+ while(actioning);
+
+ if (!actionHover) {
+ make = false;
+ return;
+ }
+
+ if (actionFunc[actionHover - 1] != nullptr)
+ std::thread(actionFunc[actionHover - 1]).detach();
+
+ actionHover = 0;
+ } else {
+ nearEntity->canMove = false;
+ ui::drawBox(vec2 {loc.x - HLINES(11), loc.y}, vec2 {loc.x + HLINES(12), loc.y + actionText.size() * HLINES(8)});
+
+ for (auto &s : actionText) {
+ s.second.z = ui::putStringCentered((s.second.x = loc.x), (s.second.y = (y += fontSize * 1.15f)), s.first) / 2;
+
+ if (ui::mouse.x > s.second.x - s.second.z && ui::mouse.x < s.second.x + s.second.z &&
+ ui::mouse.y > s.second.y && ui::mouse.y < s.second.y + ui::fontSize) {
+ actionHover = i;
+ ui::setFontColor(255, 100, 100, 255);
+ ui::putStringCentered(s.second.x, s.second.y, s.first);
+ ui::setFontColor(255, 255, 255, 255);
+ }
+ i++;
+ }
+
+ ui::putStringCentered(loc.x, y + fontSize * 1.2f, nearEntity->name);
+ }
+
+ if (i == actionText.size())
+ actionHover = 0;
+
+ ui::setFontColor(255, 255, 255, 255);
+ make = false;
+ }
+ }
+}
+
+void actionAttack(void)
+{
+ ACTION_PROLOUGE;
+
+ auto m = currentWorld->getNearInteractable(*player);
+
+ if (m->type == MOBT) {
+ if (!inBattle && m != nullptr) {
+ arena->fight(currentWorld, player, Mobp(m));
+
+ ui::toggleWhiteFast();
+ ui::waitForCover();
+ currentWorld = arena;
+ ui::toggleWhiteFast();
+ }
+ } else {
+ ui::dialogBox(player->name, "", false, "%s doesn't appear to be in the mood for fighting...", m->name.c_str());
+ }
+
+ ACTION_EPILOUGE;
+}
+
+void actionAction(void)
+{
+ ACTION_PROLOUGE;
+
+ auto e = currentWorld->getNearInteractable(*player);
+
+ if (e->type == NPCT)
+ e->interact();
+
+ ACTION_EPILOUGE;
+}
#include <engine.hpp>
#include <render.hpp>
+#include <texture.hpp>
#include <fstream>
** Variables section
** --------------------------------------------------------------------------*/
-// external variables
-extern Player *player; // main.cpp?
-extern World *currentWorld; // main.cpp
-extern World *currentWorldToLeft; // main.cpp
-extern World *currentWorldToRight; // main.cpp
-extern bool inBattle; // ui.cpp?
extern std::string xmlFolder;
// particle mutex
// the path of the currently loaded XML file, externally referenced in places
std::string currentXML;
-// keeps track of information of worlds the player has left to enter arenas
-static std::vector<WorldSwitchInfo> arenaNest;
-
// pathnames of images for world themes
using StyleList = std::array<std::string, 9>;
** Functions section
** --------------------------------------------------------------------------*/
-/**
- * Creates a world object.
- * Note that all this does is nullify a pointer...
- */
-World::World(bool indoor)
- : m_Indoor(indoor), lineCount(0), worldStart(0)
-{
-}
-
-/**
- * The world destructor.
- * This will free objects used by the world itself, then free the vectors of
- * entity-related objects.
- */
-World::
-~World(void)
-{
- deleteEntities();
-}
-
-/**
- * The entity vector destroyer.
- * This function will free all memory used by all entities, and then empty the
- * vectors they were stored in.
- */
-template<class T>
-void clearPointerVector(T &vec)
-{
- while (!vec.empty()) {
- delete vec.back();
- vec.pop_back();
- }
-}
-
-void World::
-deleteEntities(void)
-{
- // free particles
- particles.clear();
- // clear light array
- light.clear();
- // free villages
- village.clear();
- // clear entity array
- clearPointerVector(entity);
-}
-
-/**
- * Generates a world of the specified width.
- * This will mainly populate the WorldData array, preparing most of the world
- * object for usage.
- */
-void World::
-generate(int width)
+void WorldSystem::generate(unsigned int width)
{
float geninc = 0;
- // check for valid width
- if (width <= 0)
- UserError("Invalid world dimensions");
-
// allocate space for world
- worldData = std::vector<WorldData> (width + GROUND_HILLINESS, WorldData { false, {0, 0}, 0, 0 });
- lineCount = worldData.size();
+ world.data = std::vector<WorldData> (width + GROUND_HILLINESS, WorldData { false, {0, 0}, 0, 0 });
// prepare for generation
- worldData.front().groundHeight = GROUND_HEIGHT_INITIAL;
- auto wditer = std::begin(worldData) + GROUND_HILLINESS;
-
- if (m_Indoor) {
- for(wditer = std::begin(worldData); wditer < std::end(worldData); wditer++) {
- auto w = &*(wditer);
- w->groundHeight = GROUND_HEIGHT_MINIMUM + 5;
- w->groundColor = 4;
+ world.data[0].groundHeight = GROUND_HEIGHT_INITIAL;
+ auto wditer = std::begin(world.data) + GROUND_HILLINESS;
+
+ if (world.indoor) {
+ for (auto &l : world.data) {
+ l.groundHeight = GROUND_HEIGHT_MINIMUM + 5;
+ l.groundColor = 4;
}
} else {
// give every GROUND_HILLINESSth entry a groundHeight value
- for (; wditer < std::end(worldData); wditer += GROUND_HILLINESS)
+ for (; wditer < std::end(world.data); wditer += GROUND_HILLINESS)
wditer[-static_cast<int>(GROUND_HILLINESS)].groundHeight = wditer[0].groundHeight + (randGet() % 8 - 4);
// create slopes from the points that were just defined, populate the rest of the WorldData structure
- for (wditer = std::begin(worldData) + 1; wditer < std::end(worldData); wditer++){
+ for (wditer = std::begin(world.data) + 1; wditer < std::end(world.data); wditer++){
auto w = &*(wditer);
if (w->groundHeight != 0)
}
// define x-coordinate of world's leftmost 'line'
- worldStart = (width - GROUND_HILLINESS) * game::HLINE / 2 * -1;
-
- // create empty star array, should be filled here as well...
- star = std::vector<vec2> (100, vec2 { 0, 400 });
- for (auto &s : star) {
- s.x = (randGet() % (static_cast<int>(-worldStart) * 2)) + worldStart;
- s.y = (randGet() % game::SCREEN_HEIGHT) + 100;
- }
+ world.startX = (width - GROUND_HILLINESS) * game::HLINE / 2 * -1;
}
static Color ambient;
-void World::draw(Player *p)
-{
- auto HLINE = game::HLINE;
-
- uint ls = light.size();
-
- GLfloat *lightCoords = new GLfloat[ls * 4];
- GLfloat *lightColors = new GLfloat[ls * 4];
-
- uint lpIndex = 0;
- uint lcIndex = 0;
-
- static bool ambientUpdaterStarted = false;
- if (!ambientUpdaterStarted) {
- ambientUpdaterStarted = true;
- std::thread([&](void) {
- while (true) {
- float v = 75 * sin((game::time::getTickCount() + (DAY_CYCLE / 2)) / (DAY_CYCLE / PI));
- float rg = std::clamp(.5f + (-v / 100.0f), 0.01f, .9f);
- float b = std::clamp(.5f + (-v / 80.0f), 0.03f, .9f);
-
- ambient = Color(rg, rg, b, 1.0f);
-
- std::this_thread::sleep_for(std::chrono::milliseconds(1));
- }
- }).detach();
- }
-
- for (uint i = 0; i < ls; i++) {
- auto &l = light[i];
- if (l.belongsTo) {
- l.loc.x = l.following->loc.x;
- l.loc.y = l.following->loc.y;
- }
- if (l.flame) {
- l.fireFlicker = 0.9f + ((rand()% 2 ) / 10.0f);
- l.fireLoc.x = l.loc.x + (rand() % 2 - 1) * 3;
- l.fireLoc.y = l.loc.y + (rand() % 2 - 1) * 3;
- } else {
- l.fireFlicker = 1;
- }
-
- lightCoords[lpIndex++] = l.loc.x;
- lightCoords[lpIndex++] = l.loc.y;
- lightCoords[lpIndex++] = 0.0;
- lightCoords[lpIndex++] = l.radius;
-
- lightColors[lcIndex++] = l.color.red;
- lightColors[lcIndex++] = l.color.green;
- lightColors[lcIndex++] = l.color.blue;
- lightColors[lcIndex++] = 1.0;
- }
-
- Render::worldShader.use();
-
- glUniform4fv(Render::worldShader.uniform[WU_light], ls, lightCoords);
- glUniform4fv(Render::worldShader.uniform[WU_light_color], ls, lightColors);
- glUniform1i(Render::worldShader.uniform[WU_light_size], ls);
-
- Render::worldShader.unuse();
-
- for (auto &e :entity)
- e->draw();
-
- // flatten grass under the player if the player is on the ground
- if (p->ground) {
- int pOffset = (p->loc.x + p->width / 2 - worldStart) / HLINE;
-
- for (unsigned int i = 0; i < worldData.size(); i++)
- worldData[i].grassUnpressed = !(i < static_cast<unsigned int>(pOffset + 6) && i > static_cast<unsigned int>(pOffset - 6));
- } else {
- for (auto &wd : worldData)
- wd.grassUnpressed = true;
- }
-
- // draw the player
- //p->draw();
-
- // draw particles like a MASTAH
- glBindTexture(GL_TEXTURE_2D, colorIndex);
- glUniform1i(Render::worldShader.uniform[WU_texture], 0);
- Render::worldShader.use();
-
- glUniform4f(Render::worldShader.uniform[WU_tex_color], 1.0, 1.0, 1.0, .8);
-
- Render::worldShader.enable();
-
- partMutex.lock();
- uint ps = particles.size();
- uint pss = ps * 6 * 5;
- uint pc = 0;
-
- std::vector<GLfloat> partVec(pss);
- auto *pIndex = &partVec[0];
- for (uint i = 0; i < ps; i++) {
- pc += 30;
- if (pc > pss) {
- // TODO resize the vector or something better than breaking
- break;
- }
- particles[i].draw(pIndex);
- }
- partMutex.unlock();
-
- glVertexAttribPointer(Render::worldShader.coord, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &partVec[0]);
- glVertexAttribPointer(Render::worldShader.tex, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &partVec[3]);
- glDrawArrays(GL_TRIANGLES, 0, ps * 6);
-
- Render::worldShader.disable();
-
- glUniform4f(Render::worldShader.uniform[WU_tex_color], 1.0, 1.0, 1.0, 1.0);
-
- Render::worldShader.unuse();
-}
-
-/**
- * Get's the world's width in pixels.
- */
-int World::
-getTheWidth(void) const
-{
- return (worldStart * -2);
-}
-
-float World::
-getWorldStart(void) const
-{
- return static_cast<float>(worldStart);
-}
-
-/**
- * Get a pointer to the most recently created light.
- * Meant to be non-constant.
- */
-Light& World::
-getLastLight(void)
-{
- return light.back();
-}
-
-/**
- * Get a pointer to the most recently created mob.
- * Meant to be non-constant.
- */
-Mob* World::
-getLastMob(void)
-{
- for (auto e = entity.rbegin(); e != entity.rend(); ++e) {
- if ((*e)->type == MOBT)
- return dynamic_cast<Mob *>(*e);
- }
-
- return nullptr;
-}
-
-/**
- * Get the interactable entity that is closest to the entity provided.
- */
-Entity* World::
-getNearInteractable(Entity &e)
-{
- auto n = std::find_if(std::begin(entity), std::end(entity), [&](Entity *&a) {
- return ((a->type == MOBT) || (a->type == NPCT) || a->type == MERCHT) &&
- e.isNear(a) && (e.left ? (a->loc.x < e.loc.x) : (a->loc.x > e.loc.x));
- });
-
- return n == std::end(entity) ? nullptr : *n;
-}
-
-Mob* World::
-getNearMob(Entity &e)
-{
- auto n = std::find_if(std::begin(entity), std::end(entity), [&](Entity *a) {
- return (a->type == MOBT && e.isNear(a) && (e.left ? (a->loc.x < e.loc.x + e.width / 2) : (a->loc.x + a->width > e.loc.x + e.width / 2)));
- });
-
- return (n == std::end(entity)) ? nullptr : dynamic_cast<Mob *>(*n);
-}
-
-
-/**
- * Get the file path for the `index`th building.
- */
-std::string World::
-getSTextureLocation(unsigned int index) const
-{
- return index < sTexLoc.size() ? sTexLoc[ index ] : "";
-}
-
-/**
- * Get the coordinates of the `index`th building, with -1 meaning the last building.
- */
-vec2 World::
-getStructurePos(int index)
-{
- if (index < 0) {
- for (auto e = entity.rbegin(); e != entity.rend(); ++e) {
- if ((*e)->type == STRUCTURET)
- return (*e)->loc;
- }
-
- return vec2 {0, 0};
- }
-
- int nth = 0;
- for (const auto &e : entity) {
- if (e->type == STRUCTURET) {
- if (index == nth)
- return e->loc;
- else
- ++nth;
- }
- }
-
- return vec2 {0, 0};
-}
-
-/**
- * Saves world data to a file.
- */
-void World::save(const std::string& s)
+bool WorldSystem::save(const std::string& s)
{
- for (const auto &e : entity)
+ (void)s;
+ /*for (const auto &e : entity)
e->saveToXML();
- currentXMLDoc.SaveFile((s.empty() ? currentXML : xmlFolder + s).c_str(), false);
-}
-
-/**
- * Sets the desired theme for the world's background.
- * The images chosen for the background layers are selected depending on the
- * world's background type.
- */
-void World::setBackground(WorldBGType bgt)
-{
- bgType = bgt;
-}
-
-/**
- * Sets the world's style.
- * The world's style will determine what sprites are used for things like\
- * generic structures.
- */
-void World::setStyle(std::string pre)
-{
- // get folder prefix
- std::string prefix = pre.empty() ? "assets/style/classic/" : pre;
- styleFolder = prefix + "bg/";
-
- for (const auto &s : buildPaths)
- sTexLoc.push_back(prefix + s);
-}
-
-/**
- * Pretty self-explanatory.
- */
-std::string World::setToLeft(std::string file)
-{
- return (toLeft = file);
-}
-
-/**
- * Pretty self-explanatory.
- */
-std::string World::setToRight(std::string file)
-{
- return (toRight = file);
-}
-
-/**
- * Pretty self-explanatory.
- */
-std::string World::getToLeft(void) const
-{
- return toLeft;
-}
-
-/**
- * Pretty self-explanatory.
- */
-std::string World::getToRight(void) const
-{
- return toRight;
-}
-
-/**
- * Attempts to go to the left world, returning either that world or itself.
- */
-WorldSwitchInfo World::goWorldLeft(Player *p)
-{
- World *tmp;
- // check if player is at world edge
- if (!toLeft.empty() && p->loc.x < worldStart + HLINES(15)) {
- // load world (`toLeft` conditional confirms existance)
- tmp = loadWorldFromPtr(currentWorldToLeft);
-
- // return pointer and new player coords
- return std::make_pair(tmp, vec2 {tmp->worldStart + tmp->getTheWidth() - (float)HLINES(15),
- tmp->worldData[tmp->lineCount - 1].groundHeight});
- }
-
- return std::make_pair(this, vec2 {0, 0});
-}
-
-/**
- * Attempts to go to the right world, returning either that world or itself.
- */
-WorldSwitchInfo World::goWorldRight(Player *p)
-{
- World *tmp;
- if (!toRight.empty() && p->loc.x + p->width > -worldStart - HLINES(15)) {
- tmp = loadWorldFromPtr(currentWorldToRight);
- return std::make_pair(tmp, vec2 {tmp->worldStart + (float)HLINES(15.0), GROUND_HEIGHT_MINIMUM} );
- }
-
- return std::make_pair(this, vec2 {0, 0});
-}
-
-void World::adoptNPC(NPC *e)
-{
- entity.push_back(e);
-}
-
-void World::adoptMob(Mob* e)
-{
- entity.push_back(e);
-}
-
-/**
- * Acts like goWorldLeft(), but takes an NPC; returning true on success.
- */
-bool World::goWorldLeft(NPC *e)
-{
- // check if entity is at world edge
- if (!toLeft.empty() && e->loc.x < worldStart + HLINES(15)) {
- currentWorldToLeft->adoptNPC(e);
-
- entity.erase(std::find(std::begin(entity), std::end(entity), e));
-
- e->loc.x = currentWorldToLeft->worldStart + currentWorldToLeft->getTheWidth() - HLINES(15);
- e->loc.y = GROUND_HEIGHT_MAXIMUM;
- ++e->outnabout;
-
- return true;
- }
-
- return false;
-}
-
-bool World::goWorldRight(NPC *e)
-{
- if (!toRight.empty() && e->loc.x + e->width > -worldStart - HLINES(15)) {
- currentWorldToRight->adoptNPC(e);
-
- entity.erase(std::find(std::begin(entity), std::end(entity), e));
-
- e->loc.x = currentWorldToRight->worldStart + HLINES(15);
- e->loc.y = GROUND_HEIGHT_MINIMUM;
- --e->outnabout;
-
- return true;
- }
+ currentXMLDoc.SaveFile((s.empty() ? currentXML : xmlFolder + s).c_str(), false);*/
return false;
}
-/**
- * Attempts to enter a building that the player is standing in front of.
- */
-WorldSwitchInfo World::goInsideStructure(Player *p)
-{
- World *tmp;
- static std::string outdoorData, outdoorName;
-
- // enter a building
- if (outdoorName.empty()) {
- auto d = std::find_if(std::begin(entity), std::end(entity), [p](const Entity *s) {
- return ((p->loc.x > s->loc.x) && (p->loc.x + p->width < s->loc.x + s->width));
- });
-
- if ((d == std::end(entity)) || dynamic_cast<Structures *>(*d)->inside.empty())
- return std::make_pair(this, vec2 {0, 0});
-
- outdoorData = currentXMLRaw;
- outdoorName = currentXML;
- currentXML = xmlFolder + dynamic_cast<Structures *>(*d)->inside;
- const char *buf = readFile(currentXML.c_str());
- currentXMLRaw = buf;
- delete[] buf;
-
- tmp = dynamic_cast<Structures *>(*d)->insideWorld;
- tmp->houseTex = dynamic_cast<Structures *>(*d)->insideTex;
-
- return std::make_pair(tmp, vec2 {0, 100});
- }
-
- // exit the building
- else {
- std::string current = ¤tXML[xmlFolder.size()];
- currentXML = outdoorName;
- currentXMLRaw = outdoorData;
- outdoorName.clear();
- outdoorData.clear();
-
- /*tmp = dynamic_cast<IndoorWorld *>(currentWorld)->outside; //loadWorldFromXML(inside.back());
-
- Structures *b = nullptr;
- for (auto &s : tmp->entity) {
- if (s->type == STRUCTURET && dynamic_cast<Structures *>(s)->inside == current) {
- b = dynamic_cast<Structures *>(s);
- break;
- }
- }
-
- if (b == nullptr)*/
- return std::make_pair(currentWorld, vec2 {0, 100});
-
- //return std::make_pair(tmp, vec2 {b->loc.x + (b->width / 2), 0});
- }
-
- return std::make_pair(this, vec2 {0, 0});
-}
-
-void World::
-addStructure(Structures *s)
-{
- entityPending.push_back(s);
-}
-
-Village *World::
-addVillage(std::string name, World *world)
-{
- village.emplace_back(name, world);
- return &village.back();
-}
-
-void World::addMob(Mob *m, vec2 coord)
-{
- m->spawn(coord.x, coord.y);
-
- entityPending.push_back(m);
-}
-
-void World::
-addNPC(NPC *n)
-{
- entityPending.push_back(n);
-}
-
-void World::
-addMerchant(float x, float y, bool housed)
-{
- Merchant *tmp = new Merchant();
-
- tmp->spawn(x, y);
-
- if (housed) {
- tmp->inside = dynamic_cast<Structures *>(*std::find_if(entity.rbegin(), entity.rend(), [&](Entity *e){ return (e->type == STRUCTURET); }));
- tmp->z = tmp->inside->z + 0.1f;
- }
-
- entityPending.push_back(tmp);
-}
-
-void World::
-addObject(std::string in, std::string p, float x, float y)
-{
- Object *tmp = new Object(in, p);
- tmp->spawn(x, y);
-
- entityPending.push_back(tmp);
-}
-
-void World::
-addParticle(float x, float y, float w, float h, float vx, float vy, Color color, int 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.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);
-}
-
-void World::
-addLight(vec2 loc, float radius, Color color)
-{
- if (light.size() < 128)
- light.emplace_back(loc, radius, color);
-}
-
-void World::
-addHole(unsigned int start, unsigned int end)
-{
- end = fmin(worldData.size(), end);
-
- for (unsigned int i = start; i < end; i++)
- worldData[i].groundHeight = 0;
-}
-
-void World::
-addHill(const ivec2 peak, const unsigned int width)
-{
- int start = peak.x - width / 2,
- end = start + width,
- offset = 0;
- const float thing = peak.y - worldData[std::clamp(start, 0, static_cast<int>(lineCount))].groundHeight;
- const float period = PI / width;
-
- if (start < 0) {
- offset = -start;
- start = 0;
- }
-
- end = fmin(worldData.size(), end);
-
- for (int i = start; i < end; i++) {
- worldData[i].groundHeight += thing * sin((i - start + offset) * period);
- if (worldData[i].groundHeight > peak.y)
- worldData[i].groundHeight = peak.y;
- }
-}
-
-Arena::Arena(void)
-{
- generate(800);
- addMob(new Door(), vec2 {100, 100});
- mmob = nullptr;
-}
-
-Arena::~Arena(void)
-{
- if (mmob != nullptr)
- mmob->die();
- deleteEntities();
-}
-
-void Arena::fight(World *leave, const Player *p, Mob *m)
-{
- inBattle = true;
-
- entity.push_back((mmob = m));
- mmob->aggressive = false;
-
- arenaNest.emplace_back(leave, p->loc);
-}
-
-WorldSwitchInfo Arena::exitArena(Player *p)
-{
- if (!mmob->isAlive() &&
- p->loc.x + p->width / 2 > mmob->loc.x &&
- p->loc.x + p->width / 2 < mmob->loc.x + HLINES(12)) {
- auto ret = arenaNest.back();
- arenaNest.pop_back();
- inBattle = !(arenaNest.empty());
-
- return ret;
- }
-
- return std::make_pair(this, vec2 {0, 0});
-}
-
-static bool loadedLeft = false;
+/*static bool loadedLeft = false;
static bool loadedRight = false;
World *loadWorldFromXML(std::string path) {
return ptr;
}
-/**
- * Loads a world from the given XML file.
- */
-
World *
loadWorldFromXMLNoTakeover(std::string path)
{
loadedLeft = false, loadedRight = false;
return ret;
}
+*/
+
+void WorldSystem::load(const std::string& file)
+{
+ std::string xmlRaw;
+ std::string xmlPath;
+
+ // check for empty file name
+ if (file.empty())
+ return;
+
+ // load file data to string
+ xmlPath = xmlFolder + file;
+ auto xmlRawData = readFile(xmlPath.c_str());
+ xmlRaw = xmlRawData;
+ delete[] xmlRawData;
+
+ // let tinyxml parse the file
+ if (xmlDoc.Parse(xmlRaw.data()) != XML_NO_ERROR)
+ UserError("XML Error: Failed to parse file (not your fault though..?)");
+
+ // look for an opening world tag
+ auto wxml = xmlDoc.FirstChildElement("World");
+ if (wxml != nullptr) {
+ wxml = wxml->FirstChildElement();
+ world.indoor = false;
+ } else {
+ wxml = xmlDoc.FirstChildElement("IndoorWorld");
+ if (wxml != nullptr) {
+ wxml = wxml->FirstChildElement();
+ world.indoor = true;
+ } else {
+ UserError("XML Error: Cannot find a <World> or <IndoorWorld> tag in " + xmlPath);
+ }
+ }
+
+ // iterate through tags
+ while (wxml) {
+ std::string tagName = wxml->Name();
+
+ // style tag
+ if (tagName == "style") {
+ world.styleFolder = wxml->StrAttribute("folder");
+
+ unsigned int styleNo;
+ if (wxml->QueryUnsignedAttribute("background", &styleNo) != XML_NO_ERROR)
+ UserError("XML Error: No background given in <style> in " + xmlPath);
+
+ world.style = static_cast<WorldBGType>(styleNo);
+ world.bgm = wxml->StrAttribute("bgm");
+
+ bgFiles.clear();
+
+ const auto& files = bgPaths[(int)world.style];
+
+ for (const auto& f : files)
+ bgFiles.push_back(world.styleFolder + "bg/" + f);
+
+ bgTex = TextureIterator(bgFiles);
+ }
+
+ // world generation
+ else if (tagName == "generation") {
+ generate(wxml->UnsignedAttribute("width") / game::HLINE);
+ }
+
+ // indoor stuff
+ else if (tagName == "house") {
+ if (!world.indoor)
+ UserError("<house> can only be used inside <IndoorWorld>");
+
+ world.indoorWidth = wxml->FloatAttribute("width");
+ world.indoorTex = Texture::loadTexture(wxml->Attribute("texture"));
+ }
+
+ // weather tag
+ else if (tagName == "weather") {
+ setWeather(wxml->GetText());
+ }
+
+ // link tags
+ else if (tagName == "link") {
+ auto linkTo = wxml->Attribute("left");
+ if (linkTo != nullptr) {
+ world.toLeft = linkTo;
+ } else {
+ linkTo = wxml->Attribute("right");
+ if (linkTo != nullptr)
+ world.toRight = linkTo;
+ else
+ UserError("<link> doesn't handle left or right... huh");
+ }
+ }
+
+ // time setting
+ else if (tagName == "time") {
+ game::time::setTickCount(std::stoi(wxml->GetText()));
+ }
+
+ wxml = wxml->NextSiblingElement();
+ }
+}
+/*
World *
loadWorldFromXMLNoSave(std::string path) {
XMLDocument *_currentXMLDoc;
const char *ptr;
std::string name, sptr;
- // no file? -> no world
- if (path.empty())
- return nullptr;
-
- _currentXML = xmlFolder + path;
- const char *worthless = readFile(_currentXML.c_str());
- _currentXMLRaw = worthless;
- delete[] worthless;
-
- // 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"))) {
- wxml = wxml->FirstChildElement();
- vil = _currentXMLDoc->FirstChildElement("World")->FirstChildElement("village");
- tmp = new World();
- Indoor = false;
- }
-
- // attempt to load an <IndoorWorld> tag
- else if ((wxml = _currentXMLDoc->FirstChildElement("IndoorWorld"))) {
- wxml = wxml->FirstChildElement();
- vil = NULL;
- tmp = new World(true);
- Indoor = true;
- }
-
- // error: can't load a world...
- else
- UserError("XML Error: Cannot find a <World> or <IndoorWorld> tag in " + _currentXML + "!");
-
// iterate through world tags
while (wxml) {
newEntity = nullptr;
}
- // style tags
- else if (name == "style") {
- // set style folder
- tmp->setStyle(wxml->StrAttribute("folder"));
-
- // set background folder
- 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->bgm = wxml->StrAttribute("bgm");
- }
-
- // world generation (for outdoor areas)
- else if (name == "generation") {
- tmp->generate(wxml->UnsignedAttribute("width") / game::HLINE);
- }
-
- else if (name == "house") {
- if (Indoor)
- tmp->HouseWidth = wxml->FloatAttribute("width");
- else
- UserError("<house> can only be used with indoor worlds");
- }
-
- // weather tags
- else if (name == "weather") {
- game::engine.getSystem<WorldSystem>()->setWeather(wxml->GetText());
- }
-
// set spawn x for player
else if (name == "spawnx" && !(loadedLeft | loadedRight)) {
player->loc.x = std::stoi(wxml->GetText());
tmp->addHill(ivec2 { wxml->IntAttribute("peakx"), wxml->IntAttribute("peaky") }, wxml->UnsignedAttribute("width"));
}
- // time setting
- else if (name == "time" && !(loadedLeft | loadedRight)) {
- game::time::setTickCount(std::stoi(wxml->GetText()));
- }
-
if (newEntity != nullptr) {
//bool alive = true;
//if (wxml->QueryBoolAttribute("alive", &alive) != XML_NO_ERROR || alive) {
while(vil) {
name = vil->Name();
- /**
- * READS DATA ABOUT STRUCTURE CONTAINED IN VILLAGE
- */
+ //READS DATA ABOUT STRUCTURE CONTAINED IN VILLAGE
if (name == "structure") {
s = new Structures();
}
return tmp;
-}
-
-Village::Village(std::string meme, World *w)
- : name(meme)
-{
- start.x = w->getTheWidth() / 2.0f;
- end.x = -start.x;
- in = false;
-}
-
-
+}*/
WorldSystem::WorldSystem(void)
: weather(WorldWeather::None), bgmObj(nullptr) {}
Mix_FreeMusic(bgmObj);
}
-void WorldSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt)
-{
- (void)en;
- (void)ev;
- (void)dt;
-
- // fade in music if not playing
- if (bgmObj != nullptr && !Mix_PlayingMusic())
- Mix_FadeInMusic(bgmObj, -1, 2000);
-
- // update player coords
- player->loc.y += player->vel.y * dt;
- player->loc.x += (player->vel.x * player->speed) * dt;
-
- // update entity coords
- for (auto &e : world->entity) {
- // dont let structures move?
- if (e->type != STRUCTURET && e->canMove) {
- e->loc.x += e->vel.x * dt;
- e->loc.y += e->vel.y * dt;
-
- // update boolean directions
- e->left = e->vel.x ? (e->vel.x < 0) : e->left;
- } else if (e->vel.y < 0) {
- e->loc.y += e->vel.y * dt;
- }
- }
-
- partMutex.lock();
- // iterate through particles
- world->particles.remove_if([](const Particles &part) {
- return part.duration <= 0;
- });
-
- for (auto &pa : world->particles) {
- if (pa.canMove) { // causes overhead
- pa.loc.y += pa.vel.y * dt;
- pa.loc.x += pa.vel.x * dt;
-
- 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;
- }
- }
- }
- partMutex.unlock();
-
- // add entities if need be
- auto& entityPending = world->entityPending;
-
- if (!entityPending.empty()) {
- while (entityPending.size() > 0) {
- world->entity.push_back(entityPending.back());
- entityPending.pop_back();
- }
- }
-
- // run detect stuff
- detect(dt);
-}
-
void WorldSystem::render(void)
{
const auto SCREEN_WIDTH = game::SCREEN_WIDTH;
static_cast<int>(SCREEN_WIDTH) / 2, static_cast<int>(SCREEN_HEIGHT) / 2
};
- auto& worldData = currentWorld->worldData;
- auto& star = currentWorld->star;
- auto worldStart = currentWorld->worldStart;
-
int iStart, iEnd, pOffset;
// world width in pixels
- int width = worldData.size() * HLINE;
+ int width = world.data.size() * HLINE;
// used for alpha values of background textures
int alpha;
+
+ static bool ambientUpdaterStarted = false;
+ if (!ambientUpdaterStarted) {
+ ambientUpdaterStarted = true;
+ std::thread([&](void) {
+ while (true) {
+ float v = 75 * sin((game::time::getTickCount() + (DAY_CYCLE / 2)) / (DAY_CYCLE / PI));
+ float rg = std::clamp(.5f + (-v / 100.0f), 0.01f, .9f);
+ float b = std::clamp(.5f + (-v / 80.0f), 0.03f, .9f);
+
+ ambient = Color(rg, rg, b, 1.0f);
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
+ }
+ }).detach();
+ }
+
+
switch (weather) {
case WorldWeather::Snowy:
alpha = 150;
makeWorldDrawingSimplerEvenThoughAndyDoesntThinkWeCanMakeItIntoFunctions(0, fron_tex_coord, tex_coord, 6);
// TODO make stars dynamic
- static GLuint starTex = Texture::loadTexture("assets/style/classic/bg/star.png");
+ /*static GLuint starTex = Texture::loadTexture("assets/style/classic/bg/star.png");
const static float stardim = 24;
GLfloat star_coord[star.size() * 5 * 6 + 1];
GLfloat *si = &star_coord[0];
glUniform4f(Render::worldShader.uniform[WU_tex_color], 1.0, 1.0, 1.0, 1.3 - static_cast<float>(alpha)/255.0f);
makeWorldDrawingSimplerEvenThoughAndyDoesntThinkWeCanMakeItIntoFunctions(5 * sizeof(GLfloat), &star_coord[0], &star_coord[3], star.size() * 6);
- }
+ }*/
Render::worldShader.disable();
bgTex++;
dim2 mountainDim = bgTex.getTextureDim();
auto xcoord = width / 2 * -1 + offset.x * 0.85f;
- for (unsigned int i = 0; i <= worldData.size() * HLINE / mountainDim.x; i++) {
+ for (int i = 0; i <= width / mountainDim.x; i++) {
bg_items.emplace_back(mountainDim.x * i + xcoord, GROUND_HEIGHT_MINIMUM, 8.0f);
bg_items.emplace_back(mountainDim.x * (i + 1) + xcoord, GROUND_HEIGHT_MINIMUM, 8.0f);
bg_items.emplace_back(mountainDim.x * (i + 1) + xcoord, GROUND_HEIGHT_MINIMUM + mountainDim.y, 8.0f);
bg_items.clear();
bg_tex.clear();
- if (world->isIndoor() && i == 3) {
- glBindTexture(GL_TEXTURE_2D, world->houseTex);
+ if (world.indoor && i == 3) {
+ glBindTexture(GL_TEXTURE_2D, world.indoorTex);
- bg_items.emplace_back(worldStart, GROUND_HEIGHT_MINIMUM, 7-(i*.1));
- bg_items.emplace_back(worldStart + world->HouseWidth, GROUND_HEIGHT_MINIMUM, 7-(i*.1));
- bg_items.emplace_back(worldStart + world->HouseWidth, GROUND_HEIGHT_MINIMUM + dim.y, 7-(i*.1));
+ const auto& startx = world.startX;
- bg_items.emplace_back(worldStart + world->HouseWidth, GROUND_HEIGHT_MINIMUM + dim.y, 7-(i*.1));
- bg_items.emplace_back(worldStart, GROUND_HEIGHT_MINIMUM + dim.y, 7-(i*.1));
- bg_items.emplace_back(worldStart, GROUND_HEIGHT_MINIMUM, 7-(i*.1));
+ bg_items.emplace_back(startx, GROUND_HEIGHT_MINIMUM, 7-(i*.1));
+ bg_items.emplace_back(startx + world.indoorWidth, GROUND_HEIGHT_MINIMUM, 7-(i*.1));
+ bg_items.emplace_back(startx + world.indoorWidth, GROUND_HEIGHT_MINIMUM + dim.y, 7-(i*.1));
+
+ bg_items.emplace_back(startx + world.indoorWidth, GROUND_HEIGHT_MINIMUM + dim.y, 7-(i*.1));
+ bg_items.emplace_back(startx, GROUND_HEIGHT_MINIMUM + dim.y, 7-(i*.1));
+ bg_items.emplace_back(startx, GROUND_HEIGHT_MINIMUM, 7-(i*.1));
} else {
- for (int j = worldStart; j <= -worldStart; j += dim.x) {
+ for (int j = world.startX; j <= -world.startX; j += dim.x) {
bg_items.emplace_back(j + xcoord, GROUND_HEIGHT_MINIMUM, 7-(i*.1));
bg_items.emplace_back(j + dim.x + xcoord, GROUND_HEIGHT_MINIMUM, 7-(i*.1));
bg_items.emplace_back(j + dim.x + xcoord, GROUND_HEIGHT_MINIMUM + dim.y, 7-(i*.1));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// get the line that the player is currently standing on
- pOffset = (offset.x + player->width / 2 - worldStart) / HLINE;
+ pOffset = 200;//(offset.x + player->width / 2 - worldStart) / HLINE;
// only draw world within player vision
iStart = std::clamp(static_cast<int>(pOffset - (SCREEN_WIDTH / 2 / HLINE) - GROUND_HILLINESS),
- 0, static_cast<int>(world->lineCount));
+ 0, static_cast<int>(world.data.size()));
iEnd = std::clamp(static_cast<int>(pOffset + (SCREEN_WIDTH / 2 / HLINE)),
- 0, static_cast<int>(world->lineCount));
+ 0, static_cast<int>(world.data.size()));
// draw the dirt
bgTex++;
std::vector<std::pair<vec2,vec3>> c;
for (int i = iStart; i < iEnd; i++) {
- if (worldData[i].groundHeight <= 0) { // TODO holes (andy)
- worldData[i].groundHeight = GROUND_HEIGHT_MINIMUM - 1;
+ if (world.data[i].groundHeight <= 0) { // TODO holes (andy)
+ world.data[i].groundHeight = GROUND_HEIGHT_MINIMUM - 1;
glColor4ub(0, 0, 0, 255);
} else {
safeSetColorA(150, 150, 150, 255);
}
- int ty = worldData[i].groundHeight / 64 + worldData[i].groundColor;
+ int ty = world.data[i].groundHeight / 64 + world.data[i].groundColor;
- c.push_back(std::make_pair(vec2(0, 0), vec3(worldStart + HLINES(i), worldData[i].groundHeight - GRASS_HEIGHT, -4.0f)));
- c.push_back(std::make_pair(vec2(1, 0), vec3(worldStart + HLINES(i) + HLINE, worldData[i].groundHeight - GRASS_HEIGHT, -4.0f)));
- c.push_back(std::make_pair(vec2(1, ty),vec3(worldStart + HLINES(i) + HLINE, 0, -4.0f)));
+ c.push_back(std::make_pair(vec2(0, 0), vec3(world.startX + HLINES(i), world.data[i].groundHeight - GRASS_HEIGHT, -4.0f)));
+ c.push_back(std::make_pair(vec2(1, 0), vec3(world.startX + HLINES(i) + HLINE, world.data[i].groundHeight - GRASS_HEIGHT, -4.0f)));
+ c.push_back(std::make_pair(vec2(1, ty),vec3(world.startX + HLINES(i) + HLINE, 0, -4.0f)));
- c.push_back(std::make_pair(vec2(1, ty),vec3(worldStart + HLINES(i) + HLINE, 0, -4.0f)));
- c.push_back(std::make_pair(vec2(0, ty),vec3(worldStart + HLINES(i), 0, -4.0f)));
- c.push_back(std::make_pair(vec2(0, 0), vec3(worldStart + HLINES(i), worldData[i].groundHeight - GRASS_HEIGHT, -4.0f)));
+ c.push_back(std::make_pair(vec2(1, ty),vec3(world.startX + HLINES(i) + HLINE, 0, -4.0f)));
+ c.push_back(std::make_pair(vec2(0, ty),vec3(world.startX + HLINES(i), 0, -4.0f)));
+ c.push_back(std::make_pair(vec2(0, 0), vec3(world.startX + HLINES(i), world.data[i].groundHeight - GRASS_HEIGHT, -4.0f)));
- if (worldData[i].groundHeight == GROUND_HEIGHT_MINIMUM - 1)
- worldData[i].groundHeight = 0;
+ if (world.data[i].groundHeight == GROUND_HEIGHT_MINIMUM - 1)
+ world.data[i].groundHeight = 0;
}
std::vector<GLfloat> dirtc;
Render::worldShader.disable();
Render::worldShader.unuse();
- if (!world->isIndoor()) {
+ if (!world.indoor) {
bgTex++;
safeSetColorA(255, 255, 255, 255);
std::vector<GLfloat> grasst;
for (int i = iStart; i < iEnd; i++) {
- auto wd = worldData[i];
+ auto wd = world.data[i];
auto gh = wd.grassHeight;
// flatten the grass if the player is standing on it.
// actually draw the grass.
if (wd.groundHeight) {
+ const auto& worldStart = world.startX;
+
c.push_back(std::make_pair(vec2(0, 0),vec3(worldStart + HLINES(i) , wd.groundHeight + gh[0], -3)));
c.push_back(std::make_pair(vec2(1, 0),vec3(worldStart + HLINES(i) + HLINE / 2, wd.groundHeight + gh[0], -3)));
c.push_back(std::make_pair(vec2(1, 1),vec3(worldStart + HLINES(i) + HLINE / 2, wd.groundHeight - GRASS_HEIGHT, -3)));
Render::worldShader.use();
static const GLuint rug = Texture::genColor(Color {255, 0, 0});
glBindTexture(GL_TEXTURE_2D, rug);
- vec2 ll = vec2 {worldStart, GROUND_HEIGHT_MINIMUM};
- Render::drawRect(ll, vec2 {ll.x + world->HouseWidth, ll.y + 4}, -3);
+ vec2 ll = vec2 {world.startX, GROUND_HEIGHT_MINIMUM};
+ Render::drawRect(ll, vec2 {ll.x + world.indoorWidth, ll.y + 4}, -3);
Render::worldShader.unuse();
}
- player->draw();
+ //player->draw();
}
-void WorldSystem::setWorld(World *w)
-{
- world = w;
-
- bgFiles.clear();
-
- const auto& files = bgPaths[(int)w->bgType];
-
- for (const auto& f : files)
- bgFiles.push_back(w->styleFolder + f);
-
- bgTex = TextureIterator(bgFiles);
-}
-
-
void WorldSystem::receive(const BGMToggleEvent &bte)
{
- if (bte.world == nullptr || bgmObjFile != bte.file) {
+ if (bte.world == nullptr || world.bgm != bte.file) {
Mix_FadeOutMusic(800);
if (bgmObj != nullptr)
Mix_FreeMusic(bgmObj);
- bgmObjFile = bte.file;
- bgmObj = Mix_LoadMUS(bgmObjFile.c_str());
+ //worldBgmFile = bte.file;
+ bgmObj = Mix_LoadMUS(world.bgm.c_str());
Mix_PlayMusic(bgmObj, -1);
}
}
weather = WorldWeather::None;
}
-void WorldSystem::enterWorld(World *w)
-{
- if (w != nullptr) {
- outside = world;
- world = w;
- }
-}
-
-void WorldSystem::leaveWorld(void)
-{
- world = currentWorld = outside;
-}
-
-void WorldSystem::singleDetect(Entity *e, entityx::TimeDelta dt)
+void WorldSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt)
{
- std::string killed;
- unsigned int i;
- int l;
-
- auto& worldData = world->worldData;
-
- if (e == nullptr || !(e->isAlive()))
- return;
-
- // kill dead entities
- if (e->health <= 0) {
- // die
- e->die();
- if (inBattle && e->type == MOBT)
- Mobp(e)->onDeath();
-
- // delete the entity
- for (i = 0; i < world->entity.size(); i++) {
- if (world->entity[i] == e) {
- switch (e->type) {
- case STRUCTURET:
- killed = " structure";
- break;
- case NPCT:
- killed = "n NPC";
- break;
- case MOBT:
- killed = " mob";
- break;
- case OBJECTT:
- killed = "n object";
- break;
- default:
- break;
- }
-
- std::cout << "Killed a" << killed << "...\n";
- world->entity.erase(world->entity.begin() + i);
- return;
- }
- }
-
- // exit on player death
- std::cout << "RIP " << e->name << ".\n";
- exit(0);
- }
-
- // collision / gravity: handle only living entities
- else {
-
- // forced movement gravity (sword hits)
- e->handleHits();
-
- // calculate the line that this entity is currently standing on
- l = std::clamp(static_cast<int>((e->loc.x + e->width / 2 - world->worldStart) / game::HLINE),
- 0,
- static_cast<int>(world->lineCount));
-
- // if the entity is under the world/line, pop it back to the surface
- if (e->loc.y < worldData[l].groundHeight) {
- int dir = e->vel.x < 0 ? -1 : 1;
- if (l + (dir * 2) < static_cast<int>(worldData.size()) &&
- worldData[l + (dir * 2)].groundHeight - 30 > worldData[l + dir].groundHeight) {
- e->loc.x -= (PLAYER_SPEED_CONSTANT + 2.7f) * e->speed * 2 * dir;
- e->vel.x = 0;
- } else {
- e->loc.y = worldData[l].groundHeight - 0.001f * dt;
- e->ground = true;
- e->vel.y = 0;
- }
-
- }
+ (void)en;
+ (void)ev;
+ (void)dt;
- // handle gravity if the entity is above the line
- else {
- if (e->type == STRUCTURET) {
- e->loc.y = worldData[l].groundHeight;
- e->vel.y = 0;
- e->ground = true;
- return;
- } else if (e->vel.y > -2) {
- e->vel.y -= GRAVITY_CONSTANT * dt;
- }
- }
+ // fade in music if not playing
+ if (bgmObj != nullptr && !Mix_PlayingMusic())
+ Mix_FadeInMusic(bgmObj, -1, 2000);
- // insure that the entity doesn't fall off either edge of the world.
- if (e->loc.x < world->worldStart) {
- e->vel.x = 0;
- e->loc.x = world->worldStart + HLINES(0.5f);
- } else if (e->loc.x + e->width + game::HLINE > -((int)world->worldStart)) {
- e->vel.x = 0;
- e->loc.x = -((int)world->worldStart) - e->width - game::HLINE;
- }
- }
+ // run detect stuff
+ detect(dt);
}
-void WorldSystem::detect2(entityx::TimeDelta dt)
+void WorldSystem::detect(entityx::TimeDelta dt)
{
game::entities.each<Position, Direction, Health, Solid>(
[&](entityx::Entity e, Position &loc, Direction &vel, Health &health, Solid &dim) {
UserError("die mofo");
// get the line the entity is on
- int line = std::clamp(static_cast<int>((loc.x + dim.width / 2 - world->worldStart) / game::HLINE),
+ int line = std::clamp(static_cast<int>((loc.x + dim.width / 2 - world.startX) / game::HLINE),
0,
- static_cast<int>(world->lineCount));
+ static_cast<int>(world.data.size()));
// make sure entity is above ground
- auto& data = world->worldData;
+ const auto& data = world.data;
if (loc.y < data[line].groundHeight) {
int dir = vel.x < 0 ? -1 : 1;
if (line + dir * 2 < static_cast<int>(data.size()) &&
}
// insure that the entity doesn't fall off either edge of the world.
- if (loc.x < world->worldStart) {
+ if (loc.x < world.startX) {
vel.x = 0;
- loc.x = world->worldStart + HLINES(0.5f);
- } else if (loc.x + dim.width + game::HLINE > -((int)world->worldStart)) {
+ loc.x = world.startX + HLINES(0.5f);
+ } else if (loc.x + dim.width + game::HLINE > -((int)world.startX)) {
vel.x = 0;
- loc.x = -((int)world->worldStart) - dim.width - game::HLINE;
+ loc.x = -((int)world.startX) - dim.width - game::HLINE;
}
});
}
-void WorldSystem::detect(entityx::TimeDelta dt)
-{
- int l;
-
- // handle the player
- singleDetect(player, dt);
-
- // handle other entities
- for (auto &e : world->entity)
- singleDetect(e, dt);
-
- partMutex.lock();
- // handle particles
- for (auto &part : world->particles) {
- // get particle's current world line
- l = std::clamp(static_cast<int>((part.loc.x + part.width / 2 - world->worldStart) / game::HLINE),
- 0,
- static_cast<int>(world->lineCount - 1));
- part.update(GRAVITY_CONSTANT, world->worldData[l].groundHeight);
- }
-
- // handle particle creation
- for (auto &e : world->entity) {
- if (e->type == STRUCTURET) {
- auto b = dynamic_cast<Structures *>(e);
- switch (b->bsubtype) {
- case FOUNTAIN:
- for (unsigned int r = (randGet() % 25) + 11; r--;) {
- world->addParticle(randGet() % HLINES(3) + b->loc.x + b->width / 2, // x
- b->loc.y + b->height, // y
- HLINES(1.25), // width
- HLINES(1.25), // height
- randGet() % 7 * .01 * (randGet() % 2 == 0 ? -1 : 1), // vel.x
- randGet() % 1 ? (8 + randGet() % 6) * .05 : (4 + randGet() % 6) * .05,// vel.y
- { 0, 0, 255 }, // RGB color
- 2500 // duration (ms)
- );
- world->particles.back().fountain = true;
- world->particles.back().stu = b;
- }
- break;
- case FIRE_PIT:
- for(unsigned int r = (randGet() % 20) + 11; r--;) {
- world->addParticle(randGet() % (int)(b->width / 2) + b->loc.x + b->width / 4, // x
- b->loc.y + HLINES(3), // y
- game::HLINE, // width
- game::HLINE, // height
- randGet() % 3 * .01 * (randGet() % 2 == 0 ? -1 : 1), // vel.x
- (4 + randGet() % 6) * .005, // vel.y
- { 255, 0, 0 }, // RGB color
- 400 // duration (ms)
- );
- world->particles.back().gravity = false;
- world->particles.back().behind = true;
- world->particles.back().stu = b;
- }
- break;
- default:
- break;
- }
- }
- }
- partMutex.unlock();
-
- // draws the village welcome message if the player enters the village bounds
- for (auto &v : world->village) {
- if (player->loc.x > v.start.x && player->loc.x < v.end.x) {
- if (!v.in) {
- ui::passiveImportantText(5000, "Welcome to %s", v.name.c_str());
- v.in = true;
- }
- } else {
- v.in = false;
- }
- }
-}
<generation width="1600"/>
<time>6000</time>
<spawnx>-300</spawnx>
- <npc name="Sanc" hasDialog="true" health="1" x="-324.26083" y="70.398842" dindex="9999"/>
- <npc name="Bob" hasDialog="true" spawnx="30" health="1" x="151.69295" y="71.5989" dindex="0"/>
- <structure type="1" spawnx="300" alive="1"/>
- <structure inside="bobshouse.xml" insideTexture="assets/style/classic/bg/insideWoodHouse.png" type="1" spawnx="10" alive="1"/>
- <chest alive="1"/>
+ <npc name="Sanc" hasDialog="true"/>
+ <npc name="Bob" hasDialog="true" spawnx="30"/>
+ <structure type="1" spawnx="300"/>
+ <structure inside="bobshouse.xml" insideTexture="assets/style/classic/bg/insideWoodHouse.png" type="1" spawnx="10"/>
+ <chest/>
</World>
<Dialog name="Bob">
<?xml version="1.0"?>
<IndoorWorld>
<style background="0" bgm="assets/music/theme_jazz.wav" folder="assets/style/classic/"/>
- <house width="800" />
- <generation width="1600" />
+ <house width="800"/>
+ <generation width="1600"/>
<link outside="town.xml"/>
<npc name="Bob" hasDialog="false" spawnx="30"/>
</IndoorWorld>