From cb408a63a0f03ccb0b0ce7c338527a3b4964aff9 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Thu, 20 Oct 2016 08:44:58 -0400 Subject: removed all old entity stuff --- include/entities.hpp | 541 ------------------ include/entities.hpp.bak | 541 ++++++++++++++++++ include/inventory.hpp | 284 ---------- include/inventory.hpp.bak | 284 ++++++++++ include/mob.hpp | 140 ----- include/mob.hpp.bak | 140 +++++ include/quest.hpp | 66 --- include/quest.hpp.bak | 66 +++ include/ui.hpp | 8 +- include/ui_action.hpp | 21 - include/ui_action.hpp.bak | 21 + include/ui_quest.hpp | 4 +- include/world.hpp | 390 ++----------- main.cpp | 121 ++-- src/engine.cpp | 11 +- src/entities.cpp | 1352 --------------------------------------------- src/entities.cpp.bak | 1352 +++++++++++++++++++++++++++++++++++++++++++++ src/inventory.cpp | 748 ------------------------- src/inventory.cpp.bak | 747 +++++++++++++++++++++++++ src/items.cpp | 301 ---------- src/items.cpp.bak | 301 ++++++++++ src/mob.cpp | 539 ------------------ src/mob.cpp.bak | 539 ++++++++++++++++++ src/quest.cpp | 68 --- src/quest.cpp.bak | 65 +++ src/ui.cpp | 303 +--------- src/ui_action.cpp | 143 ----- src/ui_action.cpp.bak | 143 +++++ src/ui_menu.cpp | 1 + src/world.cpp | 1244 +++++++---------------------------------- xml/!town.xml | 10 +- xml/bobshouse.xml | 4 +- 32 files changed, 4522 insertions(+), 5976 deletions(-) delete mode 100644 include/entities.hpp create mode 100644 include/entities.hpp.bak delete mode 100644 include/inventory.hpp create mode 100644 include/inventory.hpp.bak delete mode 100644 include/mob.hpp create mode 100644 include/mob.hpp.bak delete mode 100644 include/quest.hpp create mode 100644 include/quest.hpp.bak delete mode 100644 include/ui_action.hpp create mode 100644 include/ui_action.hpp.bak delete mode 100644 src/entities.cpp create mode 100644 src/entities.cpp.bak delete mode 100644 src/inventory.cpp create mode 100644 src/inventory.cpp.bak delete mode 100644 src/items.cpp create mode 100644 src/items.cpp.bak delete mode 100644 src/mob.cpp create mode 100644 src/mob.cpp.bak delete mode 100644 src/quest.cpp create mode 100644 src/quest.cpp.bak delete mode 100644 src/ui_action.cpp create mode 100644 src/ui_action.cpp.bak diff --git a/include/entities.hpp b/include/entities.hpp deleted file mode 100644 index 945e8c8..0000000 --- a/include/entities.hpp +++ /dev/null @@ -1,541 +0,0 @@ -/* ---------------------------------------------------------------------------- -** The entity stuffs. -** -** Entities. -** --------------------------------------------------------------------------*/ -#ifndef ENTITIES_H -#define ENTITIES_H -#define DEBUG - -/* ---------------------------------------------------------------------------- -** Includes section -** --------------------------------------------------------------------------*/ - -// local game includes -#include -#include -#include -#include -#include -#include - -// local library includes -#include -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::vectortrade; - 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 - -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 -#include - -class PlayerSystem : public entityx::System, public entityx::Receiver { -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 -**/ diff --git a/include/entities.hpp.bak b/include/entities.hpp.bak new file mode 100644 index 0000000..945e8c8 --- /dev/null +++ b/include/entities.hpp.bak @@ -0,0 +1,541 @@ +/* ---------------------------------------------------------------------------- +** The entity stuffs. +** +** Entities. +** --------------------------------------------------------------------------*/ +#ifndef ENTITIES_H +#define ENTITIES_H +#define DEBUG + +/* ---------------------------------------------------------------------------- +** Includes section +** --------------------------------------------------------------------------*/ + +// local game includes +#include +#include +#include +#include +#include +#include + +// local library includes +#include +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::vectortrade; + 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 + +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 +#include + +class PlayerSystem : public entityx::System, public entityx::Receiver { +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 +**/ diff --git a/include/inventory.hpp b/include/inventory.hpp deleted file mode 100644 index 533318c..0000000 --- a/include/inventory.hpp +++ /dev/null @@ -1,284 +0,0 @@ -#ifndef INVENTORY_H -#define INVENTORY_H - -#include -#include - -#include -#include - -#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 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 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; - -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 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 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 - -class InventorySystem : public entityx::System, public entityx::Receiver { -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 diff --git a/include/inventory.hpp.bak b/include/inventory.hpp.bak new file mode 100644 index 0000000..533318c --- /dev/null +++ b/include/inventory.hpp.bak @@ -0,0 +1,284 @@ +#ifndef INVENTORY_H +#define INVENTORY_H + +#include +#include + +#include +#include + +#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 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 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; + +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 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 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 + +class InventorySystem : public entityx::System, public entityx::Receiver { +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 diff --git a/include/mob.hpp b/include/mob.hpp deleted file mode 100644 index 24b8ed9..0000000 --- a/include/mob.hpp +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef MOB_H_ -#define MOB_H_ - -#include -#include - -#include -#include -#include -#include -#include - -// local library headers -#include -using namespace tinyxml2; - -extern Player *player; -extern std::string currentXML; - -using Drop = std::tuple; - -class Mob : public Entity { -protected: - XMLElement *xmle; - std::forward_list 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_ diff --git a/include/mob.hpp.bak b/include/mob.hpp.bak new file mode 100644 index 0000000..24b8ed9 --- /dev/null +++ b/include/mob.hpp.bak @@ -0,0 +1,140 @@ +#ifndef MOB_H_ +#define MOB_H_ + +#include +#include + +#include +#include +#include +#include +#include + +// local library headers +#include +using namespace tinyxml2; + +extern Player *player; +extern std::string currentXML; + +using Drop = std::tuple; + +class Mob : public Entity { +protected: + XMLElement *xmle; + std::forward_list 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_ diff --git a/include/quest.hpp b/include/quest.hpp deleted file mode 100644 index 2db65a2..0000000 --- a/include/quest.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/** @file Quest.h - * @brief The quest handling system. - * - * This file contains Quest and QuestHandler, used to manage quests inside the - * game. - */ - -#ifndef QUEST_H -#define QUEST_H - -#include - -#include - -/** - * When defined, DEBUG allows extra messages to be printed to the terminal for - * debugging purposes. - */ - -#define DEBUG - -typedef struct { - std::string title; - std::string desc; - std::pair reward; - std::vector> need; -} Quest; - -/** - * The Quest Handler class. - * - * This class handles quests, including the assigning, dropping, and completing - * of the quests. - */ - -class QuestHandler { -public: - std::vectorcurrent; - - /** - * Adds a quest to the current quest vector by its title. - */ - - int assign(std::string title,std::string desc,std::string req); - - /** - * Drops a quest through its title. - */ - - int drop(std::string title); - - /** - * Finishes a quest through it's title, also giving a pointer to the Entity - * that gave the quest originally. - */ - - int finish(std::string t); - - /** - * Returns true if this handler is currently taking the quest. - */ - - bool hasQuest(std::string t); -}; - -#endif // QUEST_H diff --git a/include/quest.hpp.bak b/include/quest.hpp.bak new file mode 100644 index 0000000..2db65a2 --- /dev/null +++ b/include/quest.hpp.bak @@ -0,0 +1,66 @@ +/** @file Quest.h + * @brief The quest handling system. + * + * This file contains Quest and QuestHandler, used to manage quests inside the + * game. + */ + +#ifndef QUEST_H +#define QUEST_H + +#include + +#include + +/** + * When defined, DEBUG allows extra messages to be printed to the terminal for + * debugging purposes. + */ + +#define DEBUG + +typedef struct { + std::string title; + std::string desc; + std::pair reward; + std::vector> need; +} Quest; + +/** + * The Quest Handler class. + * + * This class handles quests, including the assigning, dropping, and completing + * of the quests. + */ + +class QuestHandler { +public: + std::vectorcurrent; + + /** + * Adds a quest to the current quest vector by its title. + */ + + int assign(std::string title,std::string desc,std::string req); + + /** + * Drops a quest through its title. + */ + + int drop(std::string title); + + /** + * Finishes a quest through it's title, also giving a pointer to the Entity + * that gave the quest originally. + */ + + int finish(std::string t); + + /** + * Returns true if this handler is currently taking the quest. + */ + + bool hasQuest(std::string t); +}; + +#endif // QUEST_H diff --git a/include/ui.hpp b/include/ui.hpp index 8671393..c7a69b6 100644 --- a/include/ui.hpp +++ b/include/ui.hpp @@ -21,10 +21,9 @@ // local game headers #include #include -#include -#include +//#include #include -#include +//#include // local library headers #include @@ -71,7 +70,6 @@ namespace ui { extern bool posFlag; extern unsigned char dialogOptChosen; - extern unsigned char merchOptChosen; extern bool dialogBoxExists; extern bool dialogImportant; extern bool dialogPassive; @@ -123,8 +121,6 @@ namespace ui { 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); diff --git a/include/ui_action.hpp b/include/ui_action.hpp deleted file mode 100644 index a275ab3..0000000 --- a/include/ui_action.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef ACTION_H_ -#define ACTION_H_ - -#include -#include - -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_ diff --git a/include/ui_action.hpp.bak b/include/ui_action.hpp.bak new file mode 100644 index 0000000..a275ab3 --- /dev/null +++ b/include/ui_action.hpp.bak @@ -0,0 +1,21 @@ +#ifndef ACTION_H_ +#define ACTION_H_ + +#include +#include + +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_ diff --git a/include/ui_quest.hpp b/include/ui_quest.hpp index 24a5e1b..8582b67 100644 --- a/include/ui_quest.hpp +++ b/include/ui_quest.hpp @@ -27,14 +27,14 @@ namespace ui { 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); } diff --git a/include/world.hpp b/include/world.hpp index dc07267..36ccdfa 100644 --- a/include/world.hpp +++ b/include/world.hpp @@ -8,9 +8,13 @@ // local game includes #include -#include #include +#include +#include +#include +using namespace tinyxml2; + /** * The background type enum. * This enum contains all different possibilities for world backgrounds; used @@ -43,13 +47,6 @@ typedef struct { 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; - /** * Alters how bright world elements are drawn. * This value is based off of the current time of day (tick count), set in @@ -95,41 +92,6 @@ constexpr const unsigned int INDOOR_FLOOR_HEIGHTT = 400; */ 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 constexpr const char* WorldWeatherString[3] = { @@ -138,20 +100,45 @@ constexpr const char* WorldWeatherString[3] = { "Snowy" }; +struct WorldData2 { + // data + std::vector data; + float startX; + + // indoor + bool indoor; + float indoorWidth; + GLuint indoorTex; + + // links + std::string toLeft, toRight; + + // style + WorldBGType style; + std::string styleFolder; + std::vector sTexLoc; + + // music + std::string bgm; + + // village + float villageStart, villageEnd; +}; + class WorldSystem : public entityx::System, public entityx::Receiver { private: - World *world; - World *outside; + WorldData2 world; WorldWeather weather; Mix_Music *bgmObj; - std::string bgmObjFile; std::vector bgFiles; TextureIterator bgTex; + XMLDocument xmlDoc; + public: explicit WorldSystem(void); ~WorldSystem(void); @@ -160,13 +147,14 @@ public: ev.subscribe(*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(weather)]; } @@ -175,299 +163,20 @@ public: 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; - - /** - * 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 sTexLoc; - - /** - * Contains randomly generated coordinates for stars. - */ - std::vector star; - - /** - * A vector of all light elements in the world. - * - * @see addLight() - * @see getLastLight() - */ - std::vector light; - - /** - * A vector of all villages in the world. - * - * @see addVillage() - */ - std::vector village; - - std::vector 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; - - /** - * 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; - - /** - * 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); }; /** @@ -495,13 +204,4 @@ World *loadWorldFromXMLNoTakeover(std::string path); */ 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 diff --git a/main.cpp b/main.cpp index 91a2759..9fa7a55 100644 --- a/main.cpp +++ b/main.cpp @@ -21,7 +21,7 @@ using namespace tinyxml2; // local game includes #include #include -#include +//#include #include #include #include @@ -33,23 +33,12 @@ using namespace tinyxml2; ** 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; @@ -137,13 +126,13 @@ int main(int argc, char *argv[]) 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()) @@ -197,35 +186,21 @@ int main(int argc, char *argv[]) goto EXIT_ROUTINE; if (!worldActuallyUseThisXMLFile.empty()) { - delete currentWorld; - currentWorld = loadWorldFromXML(worldActuallyUseThisXMLFile); - } else if (currentWorld == nullptr) { - + game::engine.getSystem()->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()->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(currentWorld->bgm); - - game::engine.getSystem()->setWorld(currentWorld); - - // spawn the arena - arena = new Arena(); - arena->setStyle(""); - arena->setBackground(WorldBGType::Forest); - arena->bgm = "assets/music/embark.wav"; +// game::events.emit(currentWorld->bgm); // the main loop, in all of its gloriousness.. std::thread([&]{ @@ -239,7 +214,7 @@ int main(int argc, char *argv[]) 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)); } @@ -259,36 +234,24 @@ EXIT_ROUTINE: 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()->die(); return 0; // Calls everything passed to atexit } -extern std::vector 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(); @@ -300,18 +263,20 @@ void render() { 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()->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 @@ -343,10 +308,9 @@ void render() { // draw the world and player game::engine.getSystem()->render(); - currentWorld->draw(player); // draw the player's inventory - player->inv->draw(); + //player->inv->draw(); // draw the fade overlay ui::drawFade(); @@ -359,21 +323,21 @@ void render() { 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()->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; @@ -403,7 +367,7 @@ void render() { Render::textShader.unuse(); delete[] tpoint; - } + }*/ } @@ -421,14 +385,14 @@ void render() { } 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})) { @@ -437,9 +401,9 @@ void logic(){ } } 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; @@ -475,7 +439,7 @@ void logic(){ e->near = player->isNear(e); e->wander(); } - } + }*/ // calculate the world shading value worldShade = 50 * sin((game::time::getTickCount() + (DAY_CYCLE / 2)) / (DAY_CYCLE / PI)); @@ -484,10 +448,11 @@ void logic(){ ui::fadeUpdate(); // create weather particles if necessary - auto weather = game::engine.getSystem()->getWeatherId(); + /*auto weather = game::engine.getSystem()->getWeatherId(); + auto worldWidth = game::engine.getSystem()->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 @@ -500,7 +465,7 @@ void logic(){ } } 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 @@ -511,10 +476,10 @@ void logic(){ 0 // no gravity, no bounce ); } - } + }*/ // increment game ticker game::time::tick(); - NPCSelected = false; - ObjectSelected = false; + //NPCSelected = false; + //ObjectSelected = false; } diff --git a/src/engine.cpp b/src/engine.cpp index 56dee48..3d498d3 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -3,8 +3,7 @@ #include #include #include -#include -#include +//#include #include extern World *currentWorld; @@ -20,9 +19,9 @@ void Engine::init(void) { systems.add(); systems.add(); - systems.add(); +// systems.add(); systems.add(); - systems.add(&player); +// systems.add(&player); systems.configure(); @@ -37,8 +36,8 @@ void Engine::render(entityx::TimeDelta dt) void Engine::update(entityx::TimeDelta dt) { systems.update(dt); - systems.update(dt); - systems.update(dt); +// systems.update(dt); +// systems.update(dt); systems.update(dt); } diff --git a/src/entities.cpp b/src/entities.cpp deleted file mode 100644 index e005df5..0000000 --- a/src/entities.cpp +++ /dev/null @@ -1,1352 +0,0 @@ -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -///NEW -#include -#include -///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 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 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(*this); - ev.subscribe(*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(wsi.first->bgm, wsi.first); - std::tie(currentWorld, player->loc) = wsi; // using p causes segfault - game::engine.getSystem()->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(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(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(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 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(*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..."<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 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(); - } -} diff --git a/src/entities.cpp.bak b/src/entities.cpp.bak new file mode 100644 index 0000000..e005df5 --- /dev/null +++ b/src/entities.cpp.bak @@ -0,0 +1,1352 @@ +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +///NEW +#include +#include +///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 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 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(*this); + ev.subscribe(*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(wsi.first->bgm, wsi.first); + std::tie(currentWorld, player->loc) = wsi; // using p causes segfault + game::engine.getSystem()->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(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(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(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 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(*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..."<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 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(); + } +} diff --git a/src/inventory.cpp b/src/inventory.cpp deleted file mode 100644 index f7a8df7..0000000 --- a/src/inventory.cpp +++ /dev/null @@ -1,748 +0,0 @@ -#include - -#include - -#include -#include - -#include - -#include -using namespace tinyxml2; - -extern Player *player; -extern GLuint invUI; -static vec2 itemLoc; -static const unsigned char numSlot = 7; -Mix_Chunk* swordSwing; - -static std::vector currencyMap; -static std::vector 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::vectordfp(numSlot); - static std::vectoriray(numSlot); - static std::vectorcurCoord(numSlot); - static int range = 200; - - static std::vectorcurdfp(4); - static std::vectorcurRay(4); - static std::vectorcurCurCoord(4); - static int curRange = 100; - - static std::vectormassDfp(32); - static std::vectormassRay(32); - static std::vectormassOrder = {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::vectormassOrderClosing = {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 &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((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((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 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(*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(); - } -} diff --git a/src/inventory.cpp.bak b/src/inventory.cpp.bak new file mode 100644 index 0000000..1b325c0 --- /dev/null +++ b/src/inventory.cpp.bak @@ -0,0 +1,747 @@ +#include + +#include + +#include + +#include + +#include +using namespace tinyxml2; + +extern Player *player; +extern GLuint invUI; +static vec2 itemLoc; +static const unsigned char numSlot = 7; +Mix_Chunk* swordSwing; + +static std::vector currencyMap; +static std::vector 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::vectordfp(numSlot); + static std::vectoriray(numSlot); + static std::vectorcurCoord(numSlot); + static int range = 200; + + static std::vectorcurdfp(4); + static std::vectorcurRay(4); + static std::vectorcurCurCoord(4); + static int curRange = 100; + + static std::vectormassDfp(32); + static std::vectormassRay(32); + static std::vectormassOrder = {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::vectormassOrderClosing = {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 &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((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((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 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(*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(); + } +} diff --git a/src/items.cpp b/src/items.cpp deleted file mode 100644 index 180c5fa..0000000 --- a/src/items.cpp +++ /dev/null @@ -1,301 +0,0 @@ -#include -#include -#include - -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 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; -} diff --git a/src/items.cpp.bak b/src/items.cpp.bak new file mode 100644 index 0000000..180c5fa --- /dev/null +++ b/src/items.cpp.bak @@ -0,0 +1,301 @@ +#include +#include +#include + +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 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; +} diff --git a/src/mob.cpp b/src/mob.cpp deleted file mode 100644 index e78e5cd..0000000 --- a/src/mob.cpp +++ /dev/null @@ -1,539 +0,0 @@ -#include -#include -#include -#include - -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(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(d) * 100.0f) { - q.y -= 20; - ui::putTextL(q, "%d x %s", std::get(d), std::get(d).c_str()); - player->inv->addItem(std::get(d), std::get(d)); - } - } -} diff --git a/src/mob.cpp.bak b/src/mob.cpp.bak new file mode 100644 index 0000000..e78e5cd --- /dev/null +++ b/src/mob.cpp.bak @@ -0,0 +1,539 @@ +#include +#include +#include +#include + +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(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(d) * 100.0f) { + q.y -= 20; + ui::putTextL(q, "%d x %s", std::get(d), std::get(d).c_str()); + player->inv->addItem(std::get(d), std::get(d)); + } + } +} diff --git a/src/quest.cpp b/src/quest.cpp deleted file mode 100644 index aa0bb2e..0000000 --- a/src/quest.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include - -#include -#include - -extern Player *player; - -int QuestHandler::assign(std::string title,std::string desc,std::string req) { - Quest tmp; - char *tok; - - tmp.title = title; - tmp.desc = desc; - - tok = strtok(&req[0], "\n\r\t,"); - tmp.need.emplace_back("", 0); - - while (tok) { - if (!tmp.need.back().first.empty()) { - tmp.need.back().second = atoi(tok); - tmp.need.emplace_back("", 0); - } else - tmp.need.back().first = tok; - - tok = strtok(NULL, "\n\r\t,"); - } - - tmp.need.pop_back(); - current.push_back(tmp); - - return 0; -} - -int QuestHandler::drop(std::string title) { - current.erase(std::remove_if (current.begin(), - current.end(), - [&](Quest q) { return q.title == title; }), - current.end()); - - return 0; -} - -int QuestHandler::finish(std::string t) { - for (auto c = current.begin(); c != current.end(); c++) { - if ((*c).title == t) { - for (auto &n : (*c).need) { - if (player->inv->hasItem(n.first) < n.second) - return 0; - } - - for (auto &n : (*c).need) - player->inv->takeItem(n.first, n.second); - current.erase(c); - return 1; - } - } - - return 0; -} - -bool QuestHandler::hasQuest(std::string t) { - for (auto &c : current) { - if (c.title == t) - return true; - } - - return false; -} diff --git a/src/quest.cpp.bak b/src/quest.cpp.bak new file mode 100644 index 0000000..f19359e --- /dev/null +++ b/src/quest.cpp.bak @@ -0,0 +1,65 @@ +#include + +#include + +int QuestHandler::assign(std::string title,std::string desc,std::string req) { + Quest tmp; + char *tok; + + tmp.title = title; + tmp.desc = desc; + + tok = strtok(&req[0], "\n\r\t,"); + tmp.need.emplace_back("", 0); + + while (tok) { + if (!tmp.need.back().first.empty()) { + tmp.need.back().second = atoi(tok); + tmp.need.emplace_back("", 0); + } else + tmp.need.back().first = tok; + + tok = strtok(NULL, "\n\r\t,"); + } + + tmp.need.pop_back(); + current.push_back(tmp); + + return 0; +} + +int QuestHandler::drop(std::string title) { + current.erase(std::remove_if (current.begin(), + current.end(), + [&](Quest q) { return q.title == title; }), + current.end()); + + return 0; +} + +int QuestHandler::finish(std::string t) { + for (auto c = current.begin(); c != current.end(); c++) { + if ((*c).title == t) { + //for (auto &n : (*c).need) { + //if (player->inv->hasItem(n.first) < n.second) + return 0; + //} + + //for (auto &n : (*c).need) + //player->inv->takeItem(n.first, n.second); + //current.erase(c); + //return 1; + } + } + + return 0; +} + +bool QuestHandler::hasQuest(std::string t) { + for (auto &c : current) { + if (c.title == t) + return true; + } + + return false; +} diff --git a/src/ui.cpp b/src/ui.cpp index aed2f48..85b2d2b 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -13,21 +13,6 @@ extern Menu* currentMenu; 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 controlMap = { SDLK_w, SDLK_a, SDLK_d, SDLK_LSHIFT, SDLK_LCTRL, SDLK_e }; @@ -79,7 +64,6 @@ static std::vector> textToDraw; static std::vector> dialogOptText; static std::string dialogBoxText; -static std::vector merchArrowLoc (2, vec3 { 0, 0, 0 }); static bool typeOutDone = true; static bool typeOutSustain = false; @@ -183,7 +167,6 @@ namespace ui { bool dialogPassive = false; bool dialogMerchant = false; int dialogPassiveTime = 0; - Trade merchTrade; int fontTransInv = 255; @@ -194,7 +177,6 @@ namespace ui { bool dialogBoxExists = false; bool dialogImportant = false; unsigned char dialogOptChosen = 0; - unsigned char merchOptChosen = 0; unsigned int textWrapLimit = 0; @@ -582,54 +564,6 @@ namespace ui { ret.clear(); } - void merchantBox(const char *name,Trade trade,const char *opt,bool passive,const char *text,...) { - va_list dialogArgs; - std::unique_ptr 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. */ @@ -904,7 +838,7 @@ namespace ui { auto SCREEN_HEIGHT = static_cast(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(); @@ -960,132 +894,6 @@ namespace ui { 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); @@ -1125,15 +933,15 @@ namespace ui { } 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()) { @@ -1174,13 +982,13 @@ namespace ui { 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; @@ -1201,7 +1009,7 @@ namespace ui { hub.x = offset.x - SCREEN_WIDTH/2 + 45*4*1.5; putStringCentered(hub.x,hub.y,"Inventory:"); - } + }*/ setFontColor(255,255,255,255); } } @@ -1248,26 +1056,8 @@ namespace ui { } } - 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) { @@ -1441,18 +1231,12 @@ void InputSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, 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) { @@ -1467,21 +1251,13 @@ void InputSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, 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(); @@ -1492,31 +1268,13 @@ void InputSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, } 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: @@ -1534,13 +1292,16 @@ void InputSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, case SDL_KEYUP: ev.emit(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) { @@ -1550,30 +1311,10 @@ void InputSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, 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. @@ -1585,10 +1326,10 @@ void InputSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, 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; diff --git a/src/ui_action.cpp b/src/ui_action.cpp deleted file mode 100644 index 9029907..0000000 --- a/src/ui_action.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#include -#include - -#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> 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 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; -} diff --git a/src/ui_action.cpp.bak b/src/ui_action.cpp.bak new file mode 100644 index 0000000..9029907 --- /dev/null +++ b/src/ui_action.cpp.bak @@ -0,0 +1,143 @@ +#include +#include + +#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> 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 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; +} diff --git a/src/ui_menu.cpp b/src/ui_menu.cpp index 4b4b05c..cbe7718 100644 --- a/src/ui_menu.cpp +++ b/src/ui_menu.cpp @@ -2,6 +2,7 @@ #include #include +#include #include diff --git a/src/world.cpp b/src/world.cpp index ef9969f..2772160 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -47,12 +47,6 @@ void makeWorldDrawingSimplerEvenThoughAndyDoesntThinkWeCanMakeItIntoFunctions_Ju ** 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 @@ -73,9 +67,6 @@ constexpr const unsigned int GRASS_HEIGHT = 4; // 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 arenaNest; - // pathnames of images for world themes using StyleList = std::array; @@ -120,88 +111,29 @@ XMLDocument currentXMLDoc; ** 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 -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 (width + GROUND_HILLINESS, WorldData { false, {0, 0}, 0, 0 }); - lineCount = worldData.size(); + world.data = std::vector (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(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) @@ -216,585 +148,22 @@ generate(int width) } // 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 (100, vec2 { 0, 400 }); - for (auto &s : star) { - s.x = (randGet() % (static_cast(-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(pOffset + 6) && i > static_cast(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 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(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(*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(*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(*d)->inside.empty()) - return std::make_pair(this, vec2 {0, 0}); - - outdoorData = currentXMLRaw; - outdoorName = currentXML; - currentXML = xmlFolder + dynamic_cast(*d)->inside; - const char *buf = readFile(currentXML.c_str()); - currentXMLRaw = buf; - delete[] buf; - - tmp = dynamic_cast(*d)->insideWorld; - tmp->houseTex = dynamic_cast(*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(currentWorld)->outside; //loadWorldFromXML(inside.back()); - - Structures *b = nullptr; - for (auto &s : tmp->entity) { - if (s->type == STRUCTURET && dynamic_cast(s)->inside == current) { - b = dynamic_cast(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(*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(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) { @@ -823,10 +192,6 @@ World *loadWorldFromPtr(World *ptr) return ptr; } -/** - * Loads a world from the given XML file. - */ - World * loadWorldFromXMLNoTakeover(std::string path) { @@ -835,7 +200,110 @@ 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 or 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