From: drumsetmonkey Date: Tue, 1 Mar 2016 13:00:55 +0000 (-0500) Subject: Work on merchants and yer mum X-Git-Url: https://code.bitgloo.com/?a=commitdiff_plain;h=97c701f329bf3da154c23b0529f194d4d8823287;p=clyne%2Fgamedev.git Work on merchants and yer mum --- 97c701f329bf3da154c23b0529f194d4d8823287 diff --cc assets/style/classic/stall.png index 0000000,0000000..1ac9844 new file mode 100644 Binary files differ diff --cc include/entities.h index 6c8e658,926eeae..545f0a4 --- a/include/entities.h +++ b/include/entities.h @@@ -47,11 -47,9 +47,29 @@@ 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; class Particles{ @@@ -197,26 -195,6 +215,15 @@@ public void wander(int); }; +class Merchant : public NPC{ +public: - union BSINV{ - struct EQUAL{ - std::string item1; - std::string item2; - }; - - struct COST{ - std::string item; - int price; - }; - }; - std::vectorbsinv; ++ std::vectorbsinv; + void interact(); + + Merchant(); + ~Merchant(); +}; + class Structures : public Entity{ public: BUILD_SUB bsubtype; diff --cc include/threadpool.h index 0000000,0000000..c341673 new file mode 100644 --- /dev/null +++ b/include/threadpool.h @@@ -1,0 -1,0 +1,53 @@@ ++#ifndef THREADPOOL_H ++#define THREADPOOL_H ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++using namespace std; ++ ++class ThreadPool ++{ ++public: ++ ++ // Constructor. ++ ThreadPool(int threads); ++ ++ // Destructor. ++ ~ThreadPool(); ++ ++ // Adds task to a task queue. ++ void Enqueue(function f); ++ ++ // Shut down the pool. ++ void ShutDown(); ++ ++private: ++ // Thread pool storage. ++ vector threadPool; ++ ++ // Queue to keep track of incoming tasks. ++ queue> 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 diff --cc include/ui.h index 0499570,3e4fc8a..667a581 --- a/include/ui.h +++ b/include/ui.h @@@ -22,7 -22,7 +22,6 @@@ typedef void(*menuFunc)() struct menuItem{ int member; union{ -- struct{ vec2 loc; dim2 dim; @@@ -30,7 -30,7 +29,6 @@@ const char* text; menuFunc func; }button; -- struct{ vec2 loc; dim2 dim; @@@ -148,7 -148,6 +146,8 @@@ namespace ui */ void dialogBox(const char *name,const char *opt,bool passive,const char *text,...); - void merchantBox(const char *name,const char *opt,bool passive,const char *text,...); ++ void merchantBox(const char *name, std::vector *items, const char *opt,bool passive,const char *text,...); ++ void merchantBox(); void waitForDialog(void); /* diff --cc include/world.h index 7338097,56f1577..228defa --- a/include/world.h +++ b/include/world.h @@@ -81,28 -81,56 +81,58 @@@ typedef struct line_t unsigned char color; /**< Lightness of dirt (brown) */ } line_t; - /* - * Handle all logic that has to do with villages + class World; + + /** + * The village class, used to group structures into villages. */ + class Village { + public: + + /** + * The name of the village. + */ - struct Village{ std::string name; + + /** + * The coordinate of where the village starts. + * + * This is used to check if the player has entered the village's area. + */ + vec2 start; + + /** + * The coordinate of where the village ends. + * + * This is used to check if the player has entered the village's area. + */ + vec2 end; + + /** + * TODO + */ + bool in; + /** + * A vector of all structures that are associated with this village. + */ + std::vector build; - Village(const char *meme){ - name = meme; - end.x = -0xffffffff; - start.x = 0xffffffff; - in = false; - } + + /** + * Creates a village of name `meme` in the world `w`. + */ + + Village(const char *meme, World *w); }; +extern Player *player; + /** * The world class. This class does everything a world should do. */ diff --cc main.cpp index cb28bcc,fa08beb..fa833fb --- a/main.cpp +++ b/main.cpp @@@ -100,79 -83,61 +83,87 @@@ Player *player extern bool worldInside; - extern Menu* currentMenu; + /** + * TODO + */ - /* - * tickCount contains the number of ticks generated since main loop entrance. - * This variable might be used anywhere. - * - * deltaTime is used for interpolation stuff. - * - * Pretty sure these variables are considered static as they might be externally - * referenced somewhere. - */ + extern Menu *currentMenu; + + /** + * The current number of ticks, used for logic operations and day/night cycles. + */ unsigned int tickCount = DAY_CYCLE; + + /** + * TODO + */ + unsigned int deltaTime = 0; - /* - * - */ + /** + * TODO + */ GLuint fragShader; + + /** + * TODO + */ + GLuint shaderProgram; - GLuint colorIndex; - GLuint mouseTex; - bool uiLoop = false; ++/** ++ * 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. +*/ + - unsigned int loops = 0; // Used for texture animation + /** + * TODO + */ - ThreadPool pool(10); + 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. + * +*/ + - extern void initEverything(void); + /** + * TODO + */ - /* - * mainLoop is in fact the main loop, which runs 'infinitely' (as long as gameRunning - * - * - * - * is set). Each loop updates timing values (tickCount and deltaTime), runs logic() - * if MSEC_PER_TICK milliseconds have passed, and then runs render(). - * - * logic handles all user input and entity/world physics. - * - * render handles all drawing to the window, calling draw functions for everything. - * - */ + GLuint mouseTex; - void logic(void); - void render(void); - void mainLoop(void); + /** + * Used for texture animation. It is externally referenced by ui.cpp + * and entities.cpp. + */ - /* - * This offset is used as the player offset in the world drawing so - * everything can be moved according to the player - */ + unsigned int loops = 0; + + /** + * Gives a coordinate based off of the player's location to allow for drawing to + * be in a constant 'absolute' place on the window. + */ - vec2 offset; /* OFFSET!!!!!!!!!!!!!!!!!!!! */ + vec2 offset; Menu *currentMenu; Menu optionsMenu; diff --cc src/entities.cpp index afcc9ad,6c2da81..5e8d51c --- a/src/entities.cpp +++ b/src/entities.cpp @@@ -136,36 -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 = NULL; - ++ //inv = new Inventory(1); ++ + //randDialog = rand() % RAND_DIALOG_COUNT - 1; + dialogIndex = 0; +} + +Merchant::~Merchant(){ - while(!aiFunc.empty()){ ++ /*while(!aiFunc.empty()){ + aiFunc.pop_back(); - } ++ }*/ + - delete inv; - delete tex; - delete[] name; ++ //delete inv; ++ //delete tex; ++ //delete[] name; +} + Structures::Structures(){ //sets the structure type health = maxHealth = 1; @@@ -457,10 -425,6 +457,12 @@@ void NPC::interact(){ //have the npc's canMove=true; } +void Merchant::interact(){ - ui::merchantBox(name, ":Accept:Good Bye", false, "Welcome to smithy\'s. Buy your sausages here you freaking mean lording screw-face"); ++ 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); diff --cc src/threadpool.cpp index 0000000,0000000..d49217d new file mode 100644 --- /dev/null +++ b/src/threadpool.cpp @@@ -1,0 -1,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 f) ++{ ++ // Scope based locking. ++ { ++ // Put unique lock on task mutex. ++ unique_lock lock(tasksMutex); ++ ++ // Push task into queue. ++ tasks.push(f); ++ } ++ ++ // Wake up one thread. ++ condition.notify_one(); ++} ++ ++void ThreadPool::Invoke() { ++ ++ function task; ++ while(true) ++ { ++ // Scope based locking. ++ { ++ // Put unique lock on task mutex. ++ unique_lock 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 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(); ++ } ++} diff --cc src/ui.cpp index 836a98e,0d1fb49..00c0864 --- a/src/ui.cpp +++ b/src/ui.cpp @@@ -46,17 -43,25 +43,25 @@@ static unsigned char fontColor[3] = {25 /* * Variables for dialog boxes / options. - */ + */ - static char dialogBoxText[512]; - static char *dialogOptText[4]; - static float dialogOptLoc[4][3]; + 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 bool typeOutDone = true; -static int dialogPassiveTime = 0; + + /* + * Menu-related objects + */ - extern Menu* currentMenu; + extern Menu *currentMenu; extern Menu pauseMenu; + /** + * The sound made when displaying characters with dialogBox or importantText. + */ static Mix_Chunk *dialogClick; @@@ -85,53 -106,71 +106,74 @@@ void Menu::gotoParent() } void Menu::gotoChild(){ - if(child == NULL){ + if(!child) currentMenu = NULL; - }else{ + else currentMenu = child; - } } + static vec2 premouse={0,0}; + namespace ui { - /* - * Mouse coordinates. - */ + /** + * The current position of the mouse. + */ vec2 mouse; - static vec2 premouse={0,0}; - /* - * Variety of keydown bools - */ - bool edown; - - /* - * Debugging flags. - */ + /** + * If true, debug information will be drawn to the screen. + */ + + bool debug = false; + + /** + * If true, lines should be drawn to the player when the debug menu is open. + */ - bool debug=false; bool posFlag=false; + + /** + * If true, the player will be able to move when the current dialog box is + * displayed. + */ + bool dialogPassive = false; + bool dialogMerchant = false; ++ std::vector *minv; + int dialogPassiveTime = 0; - - /* - * Dialog stuff that needs to be 'public'. - */ + /** + * When set to true the dialog box will attempt to display. + */ bool dialogBoxExists = false; + + /** + * When set to true the text will display as 'important' text. + */ + bool dialogImportant = false; + + /** + * Contains the last chosen dialog option. + */ + unsigned char dialogOptChosen = 0; + /** + * Determines how many characters can be displayed in a dialog box before + * a new line is required. + */ + unsigned int textWrapLimit = 110; - /* - * Current font size. Changing this WILL NOT change the font size, see setFontSize() for - * actual font size changing. - */ + /** + * The current font size. + * + * DO NOT change this directly, use setFontSize() instead. + */ unsigned int fontSize; @@@ -176,83 -228,81 +231,83 @@@ #ifdef DEBUG DEBUG_printf("Using font %s\n",ttf); #endif // DEBUG + } - /* - * Sets a new font size (default: 12). - */ + /** + * Sets a new font size and renders the necessary characters (default font + * size: 16; 24 for importantText). + */ void setFontSize(unsigned int size){ + mtx.lock(); unsigned int i,j; - char *buf; - fontSize=size; - - FT_Set_Pixel_Sizes(ftf,0,fontSize); + std::unique_ptr rgbaBuf; + size_t rgbaBufSize = 0; - /* - * Pre-render 'all' the characters. - */ + FT_Set_Pixel_Sizes(ftf,0,(fontSize = size)); - glDeleteTextures(93,ftex); // delete[] any already-rendered textures - glGenTextures(93,ftex); // Generate new texture name/locations? + // delete old characters, make space for new ones + for(i=0; i < FT_CHAR_COUNT; i++){ + glDeleteTextures(1, &ftmap[i].tex); + glGenTextures(1, &ftmap[i].tex); + } + // Load all characters we expect to use for(i=33;i<126;i++){ - /* - * Load the character from the font family file. - */ - //uiLoop ? std::cout << "Loop while render\n" : std::cout << "No loop while render\n"; + // Load the bitmap for the current character. if(FT_Load_Char(ftf,i,FT_LOAD_RENDER)){ std::cout<<"Error! Unsupported character "<<(char)i<<" ("<glyph->bitmap.width * ftf->glyph->bitmap.rows * 4]; + * Convert the bitmap font given to us from FreeType into an RGBA + * format, for ease of drawing. + */ + + rgbaBuf.reset(new uint8_t [(rgbaBufSize = ftf->glyph->bitmap.width * ftf->glyph->bitmap.rows * 4)]); + rgbaBufSize /= 4; - for(j=0;jglyph->bitmap.width*ftf->glyph->bitmap.rows;j++){ - buf[j*4 ]=255;//fontColor[0]; - buf[j*4+1]=255;//fontColor[1]; - buf[j*4+2]=255;//fontColor[2]; - buf[j*4+3]=ftf->glyph->bitmap.buffer[j] ? 255 : 0; - //buf[j*4+3]=ftf->glyph->bitmap.buffer[j]; + // populate the buffer + for(j=0; j < rgbaBufSize; j++){ + rgbaBuf[j * 4 ] = + rgbaBuf[j * 4 + 1] = + rgbaBuf[j * 4 + 2] = 255; + rgbaBuf[j * 4 + 3] = ftf->glyph->bitmap.buffer[j] ? 255 : 0; } - ftexwh[i-33].x=ftf->glyph->bitmap.width; - ftexwh[i-33].y=ftf->glyph->bitmap.rows; - ftexbl[i-33].x=ftf->glyph->bitmap_left; - ftexbl[i-33].y=ftf->glyph->bitmap_top; - ftexad[i-33].x=ftf->glyph->advance.x>>6; - ftexad[i-33].y=ftf->glyph->advance.y>>6; + // save important character information + ftmap[i-33].wh = { (int)ftf->glyph->bitmap.width, (int)ftf->glyph->bitmap.rows }; + ftmap[i-33].bl = { ftf->glyph->bitmap_left, ftf->glyph->bitmap_top }; + ftmap[i-33].ad = { ftf->glyph->advance.x >> 6, ftf->glyph->advance.y >> 6 }; - glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,ftf->glyph->bitmap.width,ftf->glyph->bitmap.rows,0,GL_RGBA,GL_UNSIGNED_BYTE,buf); + // do the thing + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ftf->glyph->bitmap.width, ftf->glyph->bitmap.rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgbaBuf.get()); - delete[] buf; //free(buf); + rgbaBuf.release(); } + mtx.unlock(); } - /* - * Set a color for font rendering (default: white). - */ + /** + * Set a color for font rendering (default: white). + */ void setFontColor(unsigned char r,unsigned char g,unsigned char b){ fontColor[0]=r; @@@ -423,37 -495,28 +500,29 @@@ float putText(const float x,const float y,const char *str,...){ va_list args; - char *buf; - float width; - - /* - * Create a wimpy buffer. - */ - - buf = new char[512]; //(char *)calloc(128,sizeof(char)); - memset(buf,0,512*sizeof(char)); - - /* - * Handle the formatted string, printing it to the buffer. - */ + std::unique_ptr buf (new char[512]); - va_start(args,str); - vsnprintf(buf,512,str,args); + // create the formatted string + va_start(args, str); + vsnprintf(buf.get(), 512, str, args); va_end(args); - /* - * Draw the string, free resources, return the width of the string. - */ - - width=putString(x,y,buf); - delete[] buf; //free(buf); - - return width; + return putString(x, y, buf.get()); } + + /** + * Prints a character dialog box. + * + * This function sets up the variables necessary to draw a dialog box. If + * `opt` contains a valid string, options will be printed with the dialog + * box. If the box is passive, the player will be allowed to move while it + * is being displayed. + */ + void dialogBox(const char *name,const char *opt,bool passive,const char *text,...){ ++ textWrapLimit = 110; va_list dialogArgs; - unsigned int len; - char *sopt,*soptbuf; + size_t len; dialogPassive = passive; @@@ -488,106 -542,34 +548,103 @@@ dialogOptCount--; }; - dialogOptCount = 0; dialogOptChosen = 0; - memset(&dialogOptLoc,0,sizeof(float)*12); + memset(&dialogOptLoc, 0, sizeof(float) * 12); ++ //char *sopt = (char*)malloc(255); ++ //dialogOptCount = 4; - if(opt != NULL){ - - soptbuf = new char[strlen(opt)+1]; - strcpy(soptbuf,opt); - - sopt=strtok(soptbuf,":"); - while(sopt != NULL){ - dialogOptText[dialogOptCount] = new char[strlen(sopt)+1]; //(char *)malloc(strlen(sopt)); - strcpy(dialogOptText[dialogOptCount++],sopt); - sopt=strtok(NULL,":"); + // handle options if desired + if(opt){ - std::unique_ptr soptbuf (new char[strlen(opt) + 1]); - char *sopt = strtok(soptbuf.get(), ":"); ++ //std::vector soptbuf (new char[strlen(opt) + 1]); ++ //std::unique_ptr 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,":"); } - - delete[] soptbuf; - } - /* - * Tell draw() that the box is ready. - */ - + // allow box to be displayed dialogBoxExists = true; dialogImportant = false; - if(ret) - ret[0] = '\0'; + // kill the string created by typeOut if it contains something + if(typeOutStr) + *typeOutStr = '\0'; } - void merchantBox(const char *name,const char *opt,bool passive,const char *text,...){ ++ ++ void merchantBox(const char *name,std::vector *bsinv,const char *opt,bool passive,const char *text,...){ + std::cout << "Buying and selling on the bi-weekly!" << std::endl; + va_list dialogArgs; - unsigned int len; - char *sopt,*soptbuf; ++ size_t len; + ++ minv = bsinv; + dialogPassive = passive; + - /* - * Set up the text buffer. - */ ++ // clear the buffer ++ memset(dialogBoxText, '\0', 512); + - memset(dialogBoxText,0,512); - - /* - * Get the text ready for rendering. - */ - - len=strlen(name); - strcpy(dialogBoxText ,name); - strcpy(dialogBoxText+len,": "); - len+=2; ++ // create the string ++ strcpy(dialogBoxText, name); ++ strcat(dialogBoxText, ": "); + ++ len=strlen(dialogBoxText); + va_start(dialogArgs,text); - vsnprintf(dialogBoxText+len,512-len,text,dialogArgs); ++ vsnprintf(dialogBoxText + len, 512 - len, text, dialogArgs); + va_end(dialogArgs); + - /* - * Set up option text. - */ - ++ // free old option text + while(dialogOptCount){ + if(dialogOptText[dialogOptCount]){ - delete[] dialogOptText[dialogOptCount]; //free(dialogOptText[dialogOptCount]); ++ delete[] dialogOptText[dialogOptCount]; + dialogOptText[dialogOptCount] = NULL; + } ++ + dialogOptCount--; + }; + - dialogOptCount = 0; + dialogOptChosen = 0; - memset(&dialogOptLoc,0,sizeof(float)*12); ++ memset(&dialogOptLoc, 0, sizeof(float) * 12); + - if(opt != NULL){ - - soptbuf = new char[strlen(opt)+1]; - strcpy(soptbuf,opt); - - sopt=strtok(soptbuf,":"); - while(sopt != NULL){ - dialogOptText[dialogOptCount] = new char[strlen(sopt)+1]; //(char *)malloc(strlen(sopt)); - strcpy(dialogOptText[dialogOptCount++],sopt); - sopt=strtok(NULL,":"); ++ // handle options if desired ++ if(opt){ ++ //std::unique_ptr 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,":"); + } - - delete[] soptbuf; - + } + - /* - * Tell draw() that the box is ready. - */ - ++ // allow box to be displayed + dialogBoxExists = true; + dialogImportant = false; + dialogMerchant = true; ++ textWrapLimit = 50; + - if(ret) - ret[0] = '\0'; ++ // 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. + */ + void waitForDialog(void){ do{ mainLoop(); @@@ -644,86 -642,56 +717,111 @@@ float x,y,tmp; char *rtext; + // handle dialog box / important text if(dialogBoxExists){ - rtext=typeOut(dialogBoxText); + rtext = typeOut(dialogBoxText); if(dialogImportant){ - setFontColor(255,255,255); - if(dialogPassive){ - dialogPassiveTime -= deltaTime; - if(dialogPassiveTime < 0){ - dialogPassive = false; - dialogImportant = false; - dialogBoxExists = false; - } + setFontColor(255, 255, 255); + + // handle timeout + if(dialogPassive && (dialogPassiveTime -= deltaTime) <= 0){ + dialogPassive = false; + dialogImportant = false; + dialogBoxExists = false; } + + // draw text if(fadeIntensity == 255 || dialogPassive){ setFontSize(24); - putStringCentered(offset.x,offset.y,rtext); + 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){ - /*static std::string merchOpt[3] = {"Accept", - "Cancel"};*/ - + 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); + - for(i=0;i dialogOptLoc[i][0] && - mouse.x < dialogOptLoc[i][2] && - mouse.y > dialogOptLoc[i][1] && - mouse.y < dialogOptLoc[i][1] + fontSize){ // fontSize - setFontColor(255,255,0); - putStringCentered(offset.x,dialogOptLoc[i][1],dialogOptText[i]); ++ 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{ ++ ++ setFontColor(255, 255, 255); ++ }else{ //normal dialog box + + x=offset.x-SCREEN_WIDTH/2+HLINE*8; + y=(offset.y+SCREEN_HEIGHT/2)-HLINE*8; - - - glColor3ub(255,255,255); ++ + // draw white border + glColor3ub(255, 255, 255); glBegin(GL_LINE_STRIP); - glVertex2f(x-1 ,y+1); - glVertex2f(x+1+SCREEN_WIDTH-HLINE*16,y+1); - glVertex2f(x+1+SCREEN_WIDTH-HLINE*16,y-1-SCREEN_HEIGHT/4); - glVertex2f(x-1 ,y-1-SCREEN_HEIGHT/4); - glVertex2f(x ,y+1); + glVertex2f(x - 1 , y + 1 ); + glVertex2f(x + 1 + SCREEN_WIDTH - HLINE * 16, y + 1 ); + glVertex2f(x + 1 + SCREEN_WIDTH - HLINE * 16, y - 1 - SCREEN_HEIGHT / 4 ); + glVertex2f(x - 1 , y - 1 - SCREEN_HEIGHT / 4 ); + glVertex2f(x , y + 1 ); glEnd(); - glColor3ub(0,0,0); - glRectf(x,y,x+SCREEN_WIDTH-HLINE*16,y-SCREEN_HEIGHT/4); - - rtext=typeOut(dialogBoxText); + // draw black box + glColor3ub(0, 0, 0); + glRectf(x, y, x + SCREEN_WIDTH - HLINE * 16, y - SCREEN_HEIGHT / 4); - putString(x+HLINE,y-fontSize-HLINE,rtext); + // draw typeOut'd text + putString(x + HLINE, y - fontSize - HLINE, (rtext = typeOut(dialogBoxText))); - for(i=0;i dialogOptLoc[i][0] && - mouse.x < dialogOptLoc[i][2] && - mouse.y > dialogOptLoc[i][1] && - mouse.y < dialogOptLoc[i][1] + 16 ){ // fontSize + // check for selected option + for(i = 0; i < dialogOptCount; i++){ + if(mouse.x > dialogOptLoc[i][0] && mouse.x < dialogOptLoc[i][2] && + mouse.y > dialogOptLoc[i][1] && mouse.y < dialogOptLoc[i][1] + 16 ){ dialogOptChosen = i + 1; - goto DONE; + break; + } + } ++ ++ if(dialogMerchant){ ++ for(i = 0; i < 2; i++){ + } + } - DONE: + + // handle important text if(dialogImportant){ dialogImportant = false; setFontSize(16); - //toggleBlack(); } - /*if(ui::fontSize != 16) - 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; @@@ -1378,10 -1364,10 +1499,10 @@@ 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 --cc src/world.cpp index 306933d,303d53b..9e891fb --- a/src/world.cpp +++ b/src/world.cpp @@@ -118,6 -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,6 -140,6 +143,10 @@@ while(!light.empty()){ light.pop_back(); } ++ while(!village.empty()){ ++ delete village.back(); ++ village.pop_back(); ++ } } World::~World(void){ @@@ -1545,14 -1532,14 +1548,15 @@@ World *loadWorldFromXMLNoSave(const cha 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(); } @@@ -1649,34 -1639,13 +1656,39 @@@ (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); + } } - tmp->village.back().build.push_back(tmp->build.back()); - if(tmp->village.back().build.back()->loc.x < tmp->village.back().start.x){ - tmp->village.back().start.x = tmp->village.back().build.back()->loc.x; ++ vptr->build.push_back(tmp->build.back()); + if(vptr->build.back()->loc.x < vptr->start.x){ + vptr->start.x = vptr->build.back()->loc.x; } - if(tmp->village.back().build.back()->loc.x + tmp->village.back().build.back()->width > tmp->village.back().end.x){ - tmp->village.back().end.x = tmp->village.back().build.back()->loc.x + tmp->village.back().build.back()->width; + if(vptr->build.back()->loc.x + vptr->build.back()->width > vptr->end.x){ + vptr->end.x = vptr->build.back()->loc.x + vptr->build.back()->width; } //go to the next element in the village block