diff options
-rw-r--r-- | assets/style/classic/stall.png | bin | 0 -> 778 bytes | |||
-rw-r--r-- | include/common.h | 3 | ||||
-rw-r--r-- | include/entities.h | 37 | ||||
-rw-r--r-- | include/threadpool.h | 53 | ||||
-rw-r--r-- | include/ui.h | 10 | ||||
-rw-r--r-- | include/world.h | 8 | ||||
-rw-r--r-- | main.cpp | 44 | ||||
-rw-r--r-- | src/config.cpp | 1 | ||||
-rw-r--r-- | src/entities.cpp | 51 | ||||
-rw-r--r-- | src/gameplay.cpp | 3 | ||||
-rw-r--r-- | src/threadpool.cpp | 95 | ||||
-rw-r--r-- | src/ui.cpp | 171 | ||||
-rw-r--r-- | src/world.cpp | 50 | ||||
-rw-r--r-- | xml/playerSpawnHill1.xml | 11 |
14 files changed, 493 insertions, 44 deletions
diff --git a/assets/style/classic/stall.png b/assets/style/classic/stall.png Binary files differnew file mode 100644 index 0000000..1ac9844 --- /dev/null +++ b/assets/style/classic/stall.png diff --git a/include/common.h b/include/common.h index 6ba6f03..933067b 100644 --- a/include/common.h +++ b/include/common.h @@ -18,6 +18,7 @@ #include <thread> #include <mutex> #include <future> +#include <threadpool.h> #define GLEW_STATIC #include <GL/glew.h> @@ -118,6 +119,8 @@ extern unsigned int SCREEN_WIDTH; extern unsigned int SCREEN_HEIGHT; extern bool FULLSCREEN; +extern bool uiLoop; +extern std::mutex mtx; /** * Define the length of a single HLINE. diff --git a/include/entities.h b/include/entities.h index 926eeae..545f0a4 100644 --- a/include/entities.h +++ b/include/entities.h @@ -22,13 +22,13 @@ enum _TYPE { STRUCTURET, PLAYERT, NPCT, + MERCHT, MOBT }; enum GENDER{ MALE, - FEMALE, - TRANSBULLSHIT + FEMALE }; enum MOB_SUB { @@ -47,7 +47,27 @@ enum BUILD_SUB{ HOUSE4 = 4, FOUNTAIN = 5, LAMP_POST = 6, - FIRE_PIT = 7 + FIRE_PIT = 7, + STALL_MARKET = 70, + STALL_TRADER = 71 +}; + +class BuySell{ +public: + int member; + union{ + struct{ + std::string item1; + std::string item2; + }trade; + struct{ + enum type{BUY,SELL}; + std::string item; + int price; + }cost; + }; + BuySell(){} + ~BuySell(){} }; class World; @@ -191,10 +211,19 @@ public: void addAIFunc(int (*func)(NPC *),bool preload); void clearAIFunc(void); - void interact(); + virtual void interact(); void wander(int); }; +class Merchant : public NPC{ +public: + std::vector<BuySell>bsinv; + void interact(); + + Merchant(); + ~Merchant(); +}; + class Structures : public Entity{ public: BUILD_SUB bsubtype; diff --git a/include/threadpool.h b/include/threadpool.h new file mode 100644 index 0000000..c341673 --- /dev/null +++ b/include/threadpool.h @@ -0,0 +1,53 @@ +#ifndef THREADPOOL_H +#define THREADPOOL_H + +#include <vector> +#include <queue> +#include <thread> +#include <mutex> +#include <condition_variable> +#include <iostream> +#include <unistd.h> + +using namespace std; + +class ThreadPool +{ +public: + + // Constructor. + ThreadPool(int threads); + + // Destructor. + ~ThreadPool(); + + // Adds task to a task queue. + void Enqueue(function<void()> f); + + // Shut down the pool. + void ShutDown(); + +private: + // Thread pool storage. + vector<thread> threadPool; + + // Queue to keep track of incoming tasks. + queue<function<void()>> tasks; + + // Task queue mutex. + mutex tasksMutex; + + // Condition variable. + condition_variable condition; + + // Indicates that pool needs to be shut down. + bool terminate; + + // Indicates that pool has been terminated. + bool stopped; + + // Function that will be invoked by our threads. + void Invoke(); +}; + +#endif //THRE
\ No newline at end of file diff --git a/include/ui.h b/include/ui.h index 3e4fc8a..667a581 100644 --- a/include/ui.h +++ b/include/ui.h @@ -22,7 +22,6 @@ typedef void(*menuFunc)(); struct menuItem{ int member; union{ - struct{ vec2 loc; dim2 dim; @@ -30,7 +29,6 @@ struct menuItem{ const char* text; menuFunc func; }button; - struct{ vec2 loc; dim2 dim; @@ -108,9 +106,9 @@ namespace ui { extern bool posFlag; extern unsigned char dialogOptChosen; - extern bool dialogBoxExists; - extern bool dialogImportant; - extern bool dialogPassive; + extern bool dialogBoxExists; + extern bool dialogImportant; + extern bool dialogPassive; extern unsigned int textWrapLimit; @@ -148,6 +146,8 @@ namespace ui { */ void dialogBox(const char *name,const char *opt,bool passive,const char *text,...); + void merchantBox(const char *name, std::vector<BuySell> *items, const char *opt,bool passive,const char *text,...); + void merchantBox(); void waitForDialog(void); /* diff --git a/include/world.h b/include/world.h index c066865..733daae 100644 --- a/include/world.h +++ b/include/world.h @@ -137,6 +137,8 @@ public: ~Village(void){} }; +extern Player *player; + /** * The world class. This class does everything a world should do. */ @@ -249,6 +251,10 @@ public: char *setToRight(const char *file); + void callUpdate(){ + this->update(player,deltaTime); + } + /** * A vector of pointers to every NPC, Structure, Mob, and Object in this @@ -262,6 +268,7 @@ public: */ std::vector<NPC *> npc; + std::vector<Merchant *> merchant; /** * A vector of all Structures in this world. @@ -344,6 +351,7 @@ public: */ void addNPC(float x,float y); + void addMerchant(float x, float y); /** * Adds an object to the world with the specified item id and coordinates. @@ -114,11 +114,37 @@ GLuint fragShader; GLuint shaderProgram; /** + * Threads and various variables to be used when multithreading the game, + * mutex will prevent multiple threads from changing the same data, + * and the condition_variable will wait for threads to reach the same point + */ + +std::mutex mtx; +std::condition_variable cv; +ThreadPool pool(10); + + +/* + * loops is used for texture animation. It is believed to be passed to entity + * draw functions, although it may be externally referenced instead. +*/ + +/** * TODO */ GLuint colorIndex; +/* + * initEverything + * + * Before the main loop, things like the player, entities, and worlds should + * be created. This game has not reached the point that these can be scripted + * or programmed, so this function substitues for that. It is defined in + * src/gameplay.cpp. + * +*/ + /** * TODO */ @@ -470,14 +496,16 @@ void mainLoop(void){ */ prev = currentWorld; - ui::handleEvents(); - + pool.Enqueue(ui::handleEvents); + //ui::handleEvents(); + if(prev != currentWorld){ currentWorld->bgmPlay(prev); ui::dialogBoxExists = false; } if(prevPrevTime + MSEC_PER_TICK <= currentTime){ + //pool.Enqueue(logic); logic(); prevPrevTime = currentTime; } @@ -486,6 +514,9 @@ void mainLoop(void){ * Update player and entity coordinates. */ + /*pool.Enqueue([](){ + currentWorld->update(player,deltaTime); + });*/ currentWorld->update(player,deltaTime); /* @@ -648,7 +679,7 @@ void render(){ offset.y+SCREEN_HEIGHT/2); }else if(ui::fontSize != 16) ui::setFontSize(16); - + /* * Draw UI elements. This includes the player's health bar and the dialog box. */ @@ -766,19 +797,12 @@ void logic(){ * that the NPC doesn't move when it talks to the player. */ -/*<<<<<<< HEAD - if(n->canMove) n->wander((rand() % 120 + 30)); - - if(!player->inv->usingi) n->hit = false; - if(player->inv->usingi && !n->hit && player->inv->detectCollision(vec2{n->loc.x, n->loc.y},vec2{n->loc.x+n->width,n->loc.y+n->height})){ -=======*/ if(n->canMove) n->wander((rand() % 120 + 30)); /*if(!player->inv->usingi) n->hit = false; if(player->inv->usingi && !n->hit && player->inv->detectCollision((vec2){n->loc.x, n->loc.y},(vec2){n->loc.x+n->width,n->loc.y+n->height})){ ->>>>>>> 7ab072caaaec09720ad79cfed5738e89bc60c44f n->health -= 25; n->hit = true; for(int r = 0; r < (rand()%5);r++) diff --git a/src/config.cpp b/src/config.cpp index 72a071d..45bab3f 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -56,6 +56,7 @@ void readConfig(){ } void updateConfig(){ + Mix_Volume(0,VOLUME_MASTER); Mix_Volume(1,VOLUME_SFX * (VOLUME_MASTER/100.0f)); Mix_VolumeMusic(VOLUME_MUSIC * (VOLUME_MASTER/100.0f)); diff --git a/src/entities.cpp b/src/entities.cpp index 6c2da81..5e8d51c 100644 --- a/src/entities.cpp +++ b/src/entities.cpp @@ -3,7 +3,7 @@ #include <istream> -#define RAND_DIALOG_COUNT 13 +#define RAND_DIALOG_COUNT 14 extern std::istream *names; extern unsigned int loops; @@ -125,6 +125,7 @@ NPC::NPC(){ //sets all of the NPC specific traits on object creation randDialog = rand() % RAND_DIALOG_COUNT - 1; dialogIndex = 0; } + NPC::~NPC(){ while(!aiFunc.empty()){ aiFunc.pop_back(); @@ -135,6 +136,36 @@ NPC::~NPC(){ delete[] name; } +Merchant::Merchant(){ //sets all of the Merchant specific traits on object creation + width = HLINE * 10; + height = HLINE * 16; + + type = MERCHT; //sets type to merchant + subtype = 0; + + health = maxHealth = 100; + + maxHealth = health = 100; + canMove = true; + + //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; +} + +Merchant::~Merchant(){ + /*while(!aiFunc.empty()){ + aiFunc.pop_back(); + }*/ + + //delete inv; + //delete tex; + //delete[] name; +} + Structures::Structures(){ //sets the structure type health = maxHealth = 1; @@ -143,7 +174,7 @@ Structures::Structures(){ //sets the structure type name = NULL; - inv = NULL; + //inv = NULL; canMove = false; } Structures::~Structures(){ @@ -401,7 +432,8 @@ const char *randomDialog[RAND_DIALOG_COUNT] = { "I want to have the wallpaper in our house changed. It doesn\'t really fit the environment.", "Frig.", "The sine of theta equals the opposite over the hypotenuese.", - "Did you know the developers spelt brazier as brazzier." + "Did you know the developers spelt brazier as brazzier.", + "My dad once said to me, \"Boy, you are in a game.\" I never knew what he meant by that." }; void NPC::interact(){ //have the npc's interact back to the player @@ -425,6 +457,12 @@ void NPC::interact(){ //have the npc's interact back to the player canMove=true; } +void Merchant::interact(){ + ui::merchantBox(name, &bsinv, ":Accept:Good-Bye", false, "Welcome to Smithy\'s. Buy your sausages here you freaking meme lording screw-face"); + //ui::merchantBox(); + ui::waitForDialog(); +} + void Object::interact(void){ if(questObject && alive){ ui::dialogBox(player->name,":Yes:No",false,pickupDialog); @@ -468,11 +506,18 @@ unsigned int Structures::spawn(BUILD_SUB sub, float x, float y){ //unsigned int tempN = (getRand() % 5 + 2); switch(sub){ + case STALL_MARKET: + tex = new Texturec(1, textureLoc ? textureLoc : inWorld->sTexLoc[sub].c_str()); + dim = Texture::imageDim(textureLoc ? textureLoc : inWorld->sTexLoc[sub].c_str()); + width = dim.x; + height = dim.y; + break; default: tex = new Texturec(1, textureLoc ? textureLoc : inWorld->sTexLoc[sub].c_str()); dim = Texture::imageDim(textureLoc ? textureLoc : inWorld->sTexLoc[sub].c_str()); width = dim.x; height = dim.y; + inv = NULL; break; } return 0; diff --git a/src/gameplay.cpp b/src/gameplay.cpp index e3c1171..e16e892 100644 --- a/src/gameplay.cpp +++ b/src/gameplay.cpp @@ -217,8 +217,7 @@ void commonTriggerFunc(Mob *callee){ XMLDocument xml; XMLElement *exml; - char *text,*pch; - + char *text,*pch; if(!lock){ lock = true; diff --git a/src/threadpool.cpp b/src/threadpool.cpp new file mode 100644 index 0000000..d49217d --- /dev/null +++ b/src/threadpool.cpp @@ -0,0 +1,95 @@ +#include "threadpool.h" + +// Constructor. +ThreadPool::ThreadPool(int threads) : + terminate(false), + stopped(false) +{ + // Create number of required threads and add them to the thread pool vector. + for(int i = 0; i < threads; i++) + { + threadPool.emplace_back(thread(&ThreadPool::Invoke, this)); + } +} + +void ThreadPool::Enqueue(function<void()> f) +{ + // Scope based locking. + { + // Put unique lock on task mutex. + unique_lock<mutex> lock(tasksMutex); + + // Push task into queue. + tasks.push(f); + } + + // Wake up one thread. + condition.notify_one(); +} + +void ThreadPool::Invoke() { + + function<void()> task; + while(true) + { + // Scope based locking. + { + // Put unique lock on task mutex. + unique_lock<mutex> lock(tasksMutex); + + // Wait until queue is not empty or termination signal is sent. + condition.wait(lock, [this]{ return !tasks.empty() || terminate; }); + + // If termination signal received and queue is empty then exit else continue clearing the queue. + if (terminate && tasks.empty()) + { + return; + } + + // Get next task in the queue. + task = tasks.front(); + + // Remove it from the queue. + tasks.pop(); + } + + // Execute the task. + task(); + } +} + +void ThreadPool::ShutDown() +{ + // Scope based locking. + { + // Put unique lock on task mutex. + unique_lock<mutex> lock(tasksMutex); + + // Set termination flag to true. + terminate = true; + } + + // Wake up all threads. + condition.notify_all(); + + // Join all threads. + for(thread &thread : threadPool) + { + thread.join(); + } + + // Empty workers vector. + threadPool.empty(); + + // Indicate that the pool has been shut down. + stopped = true; +} + +// Destructor. +ThreadPool::~ThreadPool() +{ + if (!stopped) + { + ShutDown(); + } +}
\ No newline at end of file @@ -49,10 +49,10 @@ static unsigned char fontColor[3] = {255,255,255}; static char dialogBoxText[512]; static char *dialogOptText[4]; +static float merchAOptLoc[2][3]; static float dialogOptLoc[4][3]; static unsigned char dialogOptCount = 0; static bool typeOutDone = true; -static int dialogPassiveTime = 0; /* * Menu-related objects @@ -142,6 +142,9 @@ namespace ui { */ bool dialogPassive = false; + bool dialogMerchant = false; + std::vector<BuySell> *minv; + int dialogPassiveTime = 0; /** * When set to true the dialog box will attempt to display. @@ -323,6 +326,7 @@ namespace ui { */ void setFontSize(unsigned int size){ + mtx.lock(); switch((fontSize = size)){ case 24: ftmapptr = ftmap24; @@ -332,6 +336,7 @@ namespace ui { ftmapptr = ftmap16; break; } + mtx.unlock(); } /** @@ -549,6 +554,7 @@ namespace ui { */ void dialogBox(const char *name,const char *opt,bool passive,const char *text,...){ + textWrapLimit = 110; va_list dialogArgs; size_t len; @@ -578,14 +584,20 @@ namespace ui { dialogOptChosen = 0; memset(&dialogOptLoc, 0, sizeof(float) * 12); + //char *sopt = (char*)malloc(255); + //dialogOptCount = 4; // handle options if desired if(opt){ - std::unique_ptr<char[]> soptbuf (new char[strlen(opt) + 1]); - char *sopt = strtok(soptbuf.get(), ":"); + //std::vector<char*> soptbuf (new char[strlen(opt) + 1]); + //std::unique_ptr<char[]> soptbuf (new char[strlen(opt) + 1]); + char soptbuf[255]; + strcpy(soptbuf, opt); + char *sopt = strtok(soptbuf, ":"); // cycle through options while(sopt){ + printf("%s",sopt); strcpy( (dialogOptText[dialogOptCount++] = new char[strlen(sopt) + 1]), sopt); sopt = strtok(NULL,":"); } @@ -599,6 +611,69 @@ namespace ui { if(typeOutStr) *typeOutStr = '\0'; } + + void merchantBox(const char *name,std::vector<BuySell> *bsinv,const char *opt,bool passive,const char *text,...){ + std::cout << "Buying and selling on the bi-weekly!" << std::endl; + va_list dialogArgs; + size_t len; + + minv = bsinv; + dialogPassive = passive; + + // clear the buffer + memset(dialogBoxText, '\0', 512); + + // create the string + strcpy(dialogBoxText, name); + strcat(dialogBoxText, ": "); + + len=strlen(dialogBoxText); + va_start(dialogArgs,text); + vsnprintf(dialogBoxText + len, 512 - len, text, dialogArgs); + va_end(dialogArgs); + + // free old option text + while(dialogOptCount){ + if(dialogOptText[dialogOptCount]){ + delete[] dialogOptText[dialogOptCount]; + dialogOptText[dialogOptCount] = NULL; + } + + dialogOptCount--; + }; + + dialogOptChosen = 0; + memset(&dialogOptLoc, 0, sizeof(float) * 12); + + // handle options if desired + if(opt){ + //std::unique_ptr<char[]> soptbuf (new char[strlen(opt) + 1]); + char soptbuf[255]; + strcpy(soptbuf, opt); + char *sopt = strtok(soptbuf, ":"); + + // cycle through options + while(sopt){ + strcpy( (dialogOptText[dialogOptCount++] = new char[strlen(sopt) + 1]), sopt); + sopt = strtok(NULL,":"); + } + } + + // allow box to be displayed + dialogBoxExists = true; + dialogImportant = false; + dialogMerchant = true; + textWrapLimit = 50; + + // kill the string created by typeOut if it contains something + if(typeOutStr) + *typeOutStr = '\0'; + } + + void merchantBox(){ + textWrapLimit = 50; + dialogMerchant = true; + } /** * Wait for a dialog box to be dismissed. @@ -697,10 +772,77 @@ namespace ui { putStringCentered(offset.x, offset.y, rtext); setFontSize(16); } - }else{ // normal dialog box - x = offset.x - SCREEN_WIDTH / 2 + HLINE * 8; - y = (offset.y + SCREEN_HEIGHT / 2) - HLINE * 8; + }else if(dialogMerchant){ + x=offset.x-SCREEN_WIDTH/6; + y=(offset.y+SCREEN_HEIGHT/2)-HLINE*8; + + + glColor3ub(255,255,255); + glBegin(GL_LINE_STRIP); + glVertex2f(x-1 ,y+1); + glVertex2f(x+1+(SCREEN_WIDTH/3),y+1); + glVertex2f(x+1+(SCREEN_WIDTH/3),y-1-SCREEN_HEIGHT*.6); + glVertex2f(x-1,y-1-SCREEN_HEIGHT*.6); + glVertex2f(x,y+1); + glEnd(); + + glColor3ub(0,0,0); + glRectf(x,y,x+SCREEN_WIDTH/3,y-SCREEN_HEIGHT*.6); + + // draw typeOut'd text + putString(x + HLINE, y - fontSize - HLINE, (rtext = typeOut(dialogBoxText))); + merchAOptLoc[0][0] = offset.x - (SCREEN_WIDTH / 6.5) - 16; + merchAOptLoc[0][1] = offset.x + (SCREEN_WIDTH / 6.5); + merchAOptLoc[1][0] = offset.y + (SCREEN_HEIGHT *.25); + merchAOptLoc[1][1] = offset.y + (SCREEN_HEIGHT *.25); + merchAOptLoc[2][0] = offset.x - (SCREEN_WIDTH / 6.5); + merchAOptLoc[2][1] = offset.x + (SCREEN_WIDTH / 6.5) + 16; + + for(i = 0; i < 2; i++){ + if(mouse.x > merchAOptLoc[0][i] && mouse.x < merchAOptLoc[2][i] && + mouse.y > merchAOptLoc[1][i] - 8 && mouse.y < merchAOptLoc[1][i] + 8){ + glColor3ub(255, 255, 0); + }else{ + glColor3ub(255,255,255); + } + } + + glBegin(GL_TRIANGLES); + glVertex2f(merchAOptLoc[0][0],merchAOptLoc[1][0]); + glVertex2f(merchAOptLoc[2][0],merchAOptLoc[1][0]-8); + glVertex2f(merchAOptLoc[2][0],merchAOptLoc[1][0]+8); + + glVertex2f(merchAOptLoc[2][1],merchAOptLoc[1][1]); + glVertex2f(merchAOptLoc[0][1],merchAOptLoc[1][1]-8); + glVertex2f(merchAOptLoc[0][1],merchAOptLoc[1][1]+8); + glEnd(); + + // draw / handle dialog options if they exist + for(i = 0; i < dialogOptCount; i++){ + setFontColor(255, 255, 255); + + // draw option + tmp = putStringCentered(offset.x, dialogOptLoc[i][1], dialogOptText[i]); + + // get coordinate information on option + dialogOptLoc[i][2] = offset.x + tmp; + dialogOptLoc[i][0] = offset.x - tmp; + dialogOptLoc[i][1] = y - SCREEN_HEIGHT / 2 - (fontSize + HLINE) * (i + 1); + + // make text yellow if the mouse hovers over the text + if(mouse.x > dialogOptLoc[i][0] && mouse.x < dialogOptLoc[i][2] && + mouse.y > dialogOptLoc[i][1] && mouse.y < dialogOptLoc[i][1] + 16 ){ + setFontColor(255, 255, 0); + putStringCentered(offset.x, dialogOptLoc[i][1], dialogOptText[i]); + } + } + + setFontColor(255, 255, 255); + }else{ //normal dialog box + x=offset.x-SCREEN_WIDTH/2+HLINE*8; + y=(offset.y+SCREEN_HEIGHT/2)-HLINE*8; + // draw white border glColor3ub(255, 255, 255); glBegin(GL_LINE_STRIP); @@ -1157,6 +1299,11 @@ namespace ui { break; } } + + if(dialogMerchant){ + for(i = 0; i < 2; i++){ + } + } // handle important text if(dialogImportant){ @@ -1164,10 +1311,10 @@ namespace ui { setFontSize(16); } - // kill the dialog box + if(dialogMerchant) dialogMerchant = false; dialogBoxExists = false; } - + void handleEvents(void){ static bool left=true,right=false; static int heyOhLetsGo = 0; @@ -1398,10 +1545,10 @@ namespace ui { pixels = new GLubyte[ 3 * SCREEN_WIDTH * SCREEN_HEIGHT]; glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels); - static std::thread scr; - scr = std::thread(takeScreenshot,pixels); - scr.detach(); - //takeScreenshot(pixels); + //static std::thread scr; + //scr = std::thread(takeScreenshot,pixels); + //scr.detach(); + takeScreenshot(pixels); std::cout << "Took screenshot" << std::endl; break; diff --git a/src/world.cpp b/src/world.cpp index eb9f12e..9e891fb 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -118,6 +118,9 @@ void World::deleteEntities(void){ delete mob.back(); mob.pop_back(); } + while(!merchant.empty()){ + merchant.pop_back(); + } while(!npc.empty()){ delete npc.back(); npc.pop_back(); @@ -144,7 +147,6 @@ void World::deleteEntities(void){ delete village.back(); village.pop_back(); } - } World::~World(void){ @@ -950,7 +952,8 @@ void World::detect(Player *p){ */ //auto pl = std::async(&World::singleDetect,this,p); - std::thread(&World::singleDetect,this, p).detach(); + //std::thread(&World::singleDetect,this, p).detach(); + singleDetect(p); /* * Handle all remaining entities in this world. @@ -958,8 +961,8 @@ void World::detect(Player *p){ //LOOOOP: for(auto &e : entity) - std::thread(&World::singleDetect,this,e).detach(); - //hey->singleDetect(e); + //std::thread(&World::singleDetect,this,e).detach(); + singleDetect(e); for(auto &part : particles){ int l; unsigned int i; @@ -1075,6 +1078,14 @@ void World::addNPC(float x,float y){ entity.push_back(npc.back()); } +void World::addMerchant(float x, float y){ + merchant.push_back(new Merchant()); + merchant.back()->spawn(x,y); + + npc.push_back(merchant.back()); + entity.push_back(npc.back()); +} + void World::addObject(/*ITEM_ID i*/std::string in,const char *p, float x, float y){ object.push_back(new Object(in,p)); object.back()->spawn(x,y); @@ -1537,14 +1548,15 @@ World *loadWorldFromXMLNoSave(const char *path){ xml.LoadFile(currentXML); wxml = xml.FirstChildElement("World"); - vil = xml.FirstChildElement("World")->FirstChildElement("village"); if(wxml){ wxml = wxml->FirstChildElement(); + vil = xml.FirstChildElement("World")->FirstChildElement("village"); Indoor = false; tmp = new World(); }else if((wxml = xml.FirstChildElement("IndoorWorld"))){ wxml = wxml->FirstChildElement(); + vil = NULL; Indoor = true; tmp = new IndoorWorld(); } @@ -1644,8 +1656,34 @@ World *loadWorldFromXMLNoSave(const char *path){ (char*)vil->Attribute("texture"), ptr); - vptr->build.push_back(tmp->build.back()); + }else if(!strcmp(name, "stall")){ + if(!strcmp(vil->Attribute("type"),"market")){ + std::cout << "Market" << std::endl; + tmp->addStructure((BUILD_SUB)70, + vil->QueryFloatAttribute("x", &spawnx) != XML_NO_ERROR ? + randx : spawnx, + 100, + (char*)vil->Attribute("texture"), + ptr); + tmp->addMerchant(0,100); + if(!strcmp(name,"buy")){ + std::cout << "Buying"; + }else if(!strcmp(name,"sell")){ + std::cout << "Selling"; + } + strcpy(tmp->merchant.back()->name,"meme"); + + }else if(!strcmp(vil->Attribute("type"),"trader")){ + std::cout << "Trader" << std::endl; + tmp->addStructure((BUILD_SUB)71, + vil->QueryFloatAttribute("x", &spawnx) != XML_NO_ERROR ? + randx : spawnx, + 100, + (char*)vil->Attribute("texture"), + ptr); + } } + vptr->build.push_back(tmp->build.back()); if(vptr->build.back()->loc.x < vptr->start.x){ vptr->start.x = vptr->build.back()->loc.x; } diff --git a/xml/playerSpawnHill1.xml b/xml/playerSpawnHill1.xml index 269b393..d84d291 100644 --- a/xml/playerSpawnHill1.xml +++ b/xml/playerSpawnHill1.xml @@ -11,9 +11,16 @@ <npc name="Ralph" hasDialog="true" /> <npc name="Johnny" hasDialog="false" /> <!-- <structure type="5" inside="playerSpawnHill1_Building1.xml" /> --> - <village name="Meme-Town"> - <structure type="0" x="-100" inside="playerSpawnHill1_Building1.xml"/> + <village name="the Cranmore Tubing Park"> + <structure type="0" x="-300" inside="playerSpawnHill1_Building1.xml"/> <structure type="5" x="-500" inside="playerSpawnHill1_Building1.xml"/> + <stall type="market" texture="assets/style/classic/stall.png"> + <buy item="Dank MayMay" cost="420"/> + <sell item="Dank MayMay" cost="666"/> + </stall> + <stall type="trader" texture="assets/style/classic/stall.png"> + <trade item="Dank MayMay" item1="Sword"/> + </stall> </village> </World> |