diff options
author | drumsetmonkey <abelleisle@roadrunner.com> | 2016-02-11 08:28:27 -0500 |
---|---|---|
committer | drumsetmonkey <abelleisle@roadrunner.com> | 2016-02-11 08:28:27 -0500 |
commit | 2a4a514b654ef0e08134a116c658d49a8f16cfe7 (patch) | |
tree | 8f33af3d9508c370a27719d3bc2089ada1abeffb | |
parent | a0afc9a192016b2bb4c185895a4082cc965e1179 (diff) | |
parent | 3033594b89f23e65b6152daa6610f991307f2f67 (diff) |
Worlds can be themed
-rw-r--r-- | Changelog | 22 | ||||
-rw-r--r-- | config/items.xml | 2 | ||||
-rw-r--r-- | config/settings.xml.example | 26 | ||||
-rw-r--r-- | include/Quest.h | 23 | ||||
-rw-r--r-- | include/inventory.h | 1 | ||||
-rw-r--r-- | src/Quest.cpp | 117 | ||||
-rw-r--r-- | src/entities.cpp | 6 | ||||
-rw-r--r-- | src/gameplay.cpp | 37 | ||||
-rw-r--r-- | src/inventory.cpp | 51 | ||||
-rw-r--r-- | src/ui.cpp | 33 | ||||
-rw-r--r-- | xml/playerSpawnHill1.xml | 40 | ||||
-rw-r--r-- | xml/playerSpawnHill1_Building1.xml | 28 |
12 files changed, 254 insertions, 132 deletions
@@ -625,3 +625,25 @@ - improved font rendering codes - added font selection to settings.xml - XML'd important text + +2/8/2016: +========= + + - partially fixed text drawing + - XML'd quest checking, working on quest requirements + - worked on XML'ing villages + +2/9/2016: +========= + + - quests can require one item for completion + - better-er text drawing + - can set world themes through XML + +2/10/2016: +========== + + - proper quest handling: multiple req's, re-classified, overall good + - began considering unique_ptr's because they're good + - fixed inventory everything + - themes work diff --git a/config/items.xml b/config/items.xml index 02d199e..02382d6 100644 --- a/config/items.xml +++ b/config/items.xml @@ -1,7 +1,7 @@ <?xml version="1.0"?> <item name="Debug" type="Tool" maxStackSize="1" width="1" height="1" sprite="assets/items/ITEM_TEST.png" /> -<item name="Dank Maymay" type="Tool" maxStackSize="420" width="10" height="10" sprite="assets/items/ITEM_TEST.png" /> +<item name="Dank MayMay" type="Tool" maxStackSize="420" width="10" height="10" sprite="assets/items/ITEM_TEST.png" /> <item name="Your Bag" type="Equip" maxStackSize="1" width="5" height="5" sprite="assets/items/ITEM_TEST.png" /> <item name="Flashlight" type="Tool" maxStackSize="1" width="4" height="8" sprite="assets/items/flashlight_off.png" /> <item name="Wood Sword" type="Sword" maxStackSize="1" width="4" height="10" sprite="assets/items/SWORD_WOOD.png" /> diff --git a/config/settings.xml.example b/config/settings.xml.example new file mode 100644 index 0000000..d9b8077 --- /dev/null +++ b/config/settings.xml.example @@ -0,0 +1,26 @@ +<?xml version="1.0"?> +<screen width="1280" height="800" fullscreen="true"/> + +<!-- + +Available fonts: + + 8-BIT WONDER.TTF + FreePixel.ttf + Perfect DOS VGA 437.ttf + Perfect DOS VGA 437 Win.ttf + PIXEAB__.TTF + PIXEARG_.TTF + VCR_OSD_MONO_1.001.ttf + +--> + +<font path="ttf/FreePixel.ttf"/> + +<hline size="3"/> + +<volume> + <master volume="100"/> + <music volume="50"/> + <sfx volume="50"/> +</volume> diff --git a/include/Quest.h b/include/Quest.h index cc01d27..8b1e142 100644 --- a/include/Quest.h +++ b/include/Quest.h @@ -20,21 +20,18 @@ #define DEBUG
+struct need_t {
+ std::string name;
+ int n;
+};
+
typedef struct {
std::string title;
std::string desc;
struct item_t reward;
+ std::vector<struct need_t> need;
} Quest;
-/*class Quest {
-public:
- char *title;
- char *desc;
- struct item_t reward;
- Quest(const char *t,const char *d,struct item_t r);
- ~Quest();
-};*/
-
/**
* The Quest Handler class.
*
@@ -50,26 +47,26 @@ public: * Adds a quest to the current quest vector by its title.
*/
- int assign(const char *t);
+ int assign(std::string title,std::string desc,std::string req);
/**
* Drops a quest through its title.
*/
- int drop(const char *t);
+ 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(const char *t,void *completer);
+ int finish(std::string t);
/**
* Returns true if this handler is currently taking the quest.
*/
- bool hasQuest(const char *t);
+ bool hasQuest(std::string t);
};
#endif // QUEST_H
diff --git a/include/inventory.h b/include/inventory.h index e5209de..af859a5 100644 --- a/include/inventory.h +++ b/include/inventory.h @@ -48,6 +48,7 @@ public: 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); diff --git a/src/Quest.cpp b/src/Quest.cpp index f0be63c..535afc5 100644 --- a/src/Quest.cpp +++ b/src/Quest.cpp @@ -1,90 +1,71 @@ #include <Quest.h>
-/*const Quest QuestList[1] = {
- Quest("Not a quest","Stop",(struct item_t){0,0})
-};*/
+#include <entities.h>
+extern Player *player;
-/*Quest::Quest(const char *t,const char *d,struct item_t r){
- title = new char[strlen(t)+1];
- desc = new char[strlen(d)+1];
- strcpy(title,t);
- strcpy(desc,d);
- memcpy(&reward,&r,sizeof(struct item_t));
-}
+int QuestHandler::assign(std::string title,std::string desc,std::string req){
+ Quest tmp;
+ char *tok;
+
+ tmp.title = title;
+ tmp.desc = desc;
-Quest::~Quest(){
- delete[] title;
- delete[] desc;
- memset(&reward,0,sizeof(struct item_t));
-}*/
+ std::unique_ptr<char[]> buf (new char[req.size()]);
-int QuestHandler::assign(const char *t){
- /*unsigned char i;
- for(i=0;i<current.size();i++){ // Make sure we don't already have this quest
- if(!strcmp(current[i]->title,t)){
-#ifdef DEBUG
- DEBUG_printf("The QuestHandler already has this quest: %s\n",t);
-#endif // DEBUG
- return -2;
- }
+ strcpy(buf.get(),req.c_str());
+ tok = strtok(buf.get(),"\n\r\t,");
+ tmp.need.push_back({"\0",0});
+
+ while(tok){
+ if(tmp.need.back().name != "\0"){
+ tmp.need.back().n = atoi(tok);
+ tmp.need.push_back({"\0",0});
+ }else
+ tmp.need.back().name = tok;
+
+ tok = strtok(NULL,"\n\r\t,");
}
- for(i=0;i<0;i++){ // Add the quest (if it really exists)
- if(!strcmp(QuestList[i].title,t)){
- current.push_back(&QuestList[i]);
-#ifdef DEBUG
- DEBUG_printf("Added quest %s, now have %u active quests.\n",t,current.size());
-#endif // DEBUG
- return current.size();
- }
-#ifdef DEBUG
- DEBUG_printf("Finding quest: %s != %s\n",t,QuestList[i].title);
-#endif // DEBUG
- }
-#ifdef DEBUG
- DEBUG_printf("Quest %s does not exist.\n",t);
-#endif // DEBUG*/
- return strcmp(t,"h");
+
+ tmp.need.pop_back();
+ current.push_back(tmp);
+
+ return 0;
}
-int QuestHandler::drop(const char *t){
- /*unsigned char i;
- for(i=0;i<current.size();i++){
- if(!strcmp(current[i]->title,t)){
+int QuestHandler::drop(std::string title){
+ for(unsigned int i=0;i<current.size();i++){
+ if(current[i].title == title){
current.erase(current.begin()+i);
- return current.size();
+ return 0;
}
- }*/
- return strcmp(t,"h");
+ }
+ return -1;
}
-int QuestHandler::finish(const char *t,void *completer){
- /*unsigned char i;
- for(i=0;i<current.size();i++){
- if(!strcmp(current[i]->title,t)){
-#ifdef DEBUG
- DEBUG_printf("Completing quest %s.\n",t);
-#endif // DEBUG
- ((Entity *)completer)->inv->addItem(current[i]->reward.id,current[i]->reward.count);
+int QuestHandler::finish(std::string t){
+ for(unsigned int i=0;i<current.size();i++){
+ if(current[i].title == t){
+ for(auto &n : current[i].need){
+ if(player->inv->hasItem(n.name) < n.n)
+ return 0;
+ }
+
+ for(auto &n : current[i].need){
+ player->inv->takeItem(n.name,n.n);
+ }
+
current.erase(current.begin()+i);
-#ifdef DEBUG
- DEBUG_printf("QuestHandler now has %u active quests.\n",current.size());
-#endif // DEBUG
- return 0;
+ return 1;
}
}
-#ifdef DEBUG
- DEBUG_printf("QuestHandler never had quest %s.\n",t);
-#endif // DEBUG*/
- return strncmp(t,(char *)completer,1);
+ return 0;
}
-bool QuestHandler::hasQuest(const char *t){
- unsigned int i;
- for(i=0;i<current.size();i++){
- if(!strcmp(current[i].title.c_str(),t)){
+bool QuestHandler::hasQuest(std::string t){
+ for(unsigned int i=0;i<current.size();i++){
+ if(current[i].title == t)
return true;
- }
}
return false;
}
diff --git a/src/entities.cpp b/src/entities.cpp index 0469ad2..e020f8b 100644 --- a/src/entities.cpp +++ b/src/entities.cpp @@ -3,6 +3,8 @@ #include <istream> +#define RAND_DIALOG_COUNT 13 + extern std::istream *names; extern unsigned int loops; @@ -117,7 +119,7 @@ NPC::NPC(){ //sets all of the NPC specific traits on object creation tex = new Texturec(1,"assets/NPC.png"); inv = new Inventory(NPC_INV_SIZE); - randDialog = rand() % 12 - 1; + randDialog = rand() % RAND_DIALOG_COUNT - 1; dialogIndex = 0; } NPC::~NPC(){ @@ -383,7 +385,7 @@ void NPC::clearAIFunc(void){ aiFunc.clear(); } -const char *randomDialog[] = { +const char *randomDialog[RAND_DIALOG_COUNT] = { "What a beautiful day it is.", "Have you ever went fast? I have.", "I heard if you complete a quest, you'll get a special reward.", diff --git a/src/gameplay.cpp b/src/gameplay.cpp index 00faf70..e252c26 100644 --- a/src/gameplay.cpp +++ b/src/gameplay.cpp @@ -33,6 +33,8 @@ int commonAIFunc(NPC *speaker){ XMLDocument xml; XMLElement *exml,*oxml; + static unsigned int oldidx = 9999; + const char *name; unsigned int idx = 0; bool stop = false; @@ -67,13 +69,26 @@ int commonAIFunc(NPC *speaker){ if((oxml = exml->FirstChildElement("quest"))){ const char *qname; + while(oxml){ if((qname = oxml->Attribute("assign"))) - player->qh.current.push_back((Quest){qname,"None",(struct item_t){0,0}}); + player->qh.assign(qname,"None",(std::string)oxml->GetText()); + else if((qname = oxml->Attribute("check"))){ + if(player->qh.hasQuest(qname) && player->qh.finish(qname)){ + goto CONT; + }else{ + oldidx = speaker->dialogIndex; + speaker->dialogIndex = oxml->UnsignedAttribute("fail"); + return commonAIFunc(speaker); + } + } + oxml = oxml->NextSiblingElement(); } } - + +CONT: + /* * Handle any 'give' requests. */ @@ -129,7 +144,7 @@ int commonAIFunc(NPC *speaker){ * Get the player's choice, then set the XMLElement to the option's block. */ - ui::dialogBox(speaker->name,optstr.c_str(),false,exml->GetText()); + ui::dialogBox(speaker->name,optstr.c_str(),false,exml->GetText()+1); ui::waitForDialog(); if(ui::dialogOptChosen) @@ -138,12 +153,12 @@ int commonAIFunc(NPC *speaker){ while(!dopt.empty()) dopt.pop_back(); }else{ - + /* * No options - simply print the text. */ - ui::dialogBox(speaker->name,"",false,exml->GetText()); + ui::dialogBox(speaker->name,NULL,false,exml->GetText()); ui::waitForDialog(); } @@ -177,10 +192,16 @@ int commonAIFunc(NPC *speaker){ return 1; }else return commonAIFunc(speaker); }else{ - speaker->dialogIndex = 9999; - return 0; + if(oldidx != 9999){ + speaker->dialogIndex = oldidx; + oldidx = 9999; + return 1; + }else{ + speaker->dialogIndex = 9999; + return 0; + } } - return 1; + //return 1; } } diff --git a/src/inventory.cpp b/src/inventory.cpp index 93bdeb6..b32b56f 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -13,7 +13,7 @@ static bool swing = false; static vec2 itemLoc; Mix_Chunk* swordSwing; -std::vector<Item *> itemMap; +static std::vector<Item *> itemMap; void items(void){ XMLDocument xml; @@ -32,7 +32,7 @@ void items(void){ itemMap.back()->texloc = exml->Attribute("sprite"); exml = exml->NextSiblingElement(); - } + } } int Inventory::addItem(std::string name,uint count){ @@ -44,7 +44,7 @@ int Inventory::addItem(std::string name,uint count){ return 0; } } - items.push_back((item_t){i,count}); + items.push_back((item_t){count,i}); return 0; } } @@ -53,22 +53,59 @@ int Inventory::addItem(std::string name,uint count){ int Inventory::takeItem(std::string name,uint count){ unsigned int id = 999999; + + /* + * Name to ID lookup + */ + for(unsigned int i=0;i<itemMap.size();i++){ if(itemMap[i]->name == name){ id = i; break; } } + + if(id == 999999) + return -1; + + /* + * Inventory lookup + */ + for(unsigned int i=0;i<items.size();i++){ if(items[i].id == id){ if(count > items[i].count) - items.erase(items.begin()+i); - else + return -(items[i].count - count); + else{ items[i].count -= count; + if(!items[i].count) + items.erase(items.begin()+i); + } return 0; } } - return -1; + return -2; +} + +int Inventory::hasItem(std::string name){ + unsigned int id = 999999; + + for(unsigned int i=0;i<itemMap.size();i++){ + if(itemMap[i]->name == name){ + id = i; + break; + } + } + + if(id == 999999) + return 0; + + for(auto &i : items){ + if(i.id == id) + return i.count; + } + + return 0; } static GLuint *itemtex; @@ -211,7 +248,7 @@ void Inventory::draw(void){ } glEnd(); glDisable(GL_TEXTURE_2D); - ui::putText(r.end.x-(itemWide/2),r.end.y-(itemWide*.9),"%s",itemMap[items[a].id]->name); + ui::putText(r.end.x-(itemWide/2),r.end.y-(itemWide*.9),"%s",itemMap[items[a].id]->name.c_str()); ui::putText(r.end.x-(itemWide/2)+(itemWide*.85),r.end.y-(itemWide/2),"%d",items[a].count); } @@ -224,9 +224,9 @@ namespace ui { buf = new char[ftf->glyph->bitmap.width * ftf->glyph->bitmap.rows * 4]; for(j=0;j<ftf->glyph->bitmap.width*ftf->glyph->bitmap.rows;j++){ - buf[j*4 ]=fontColor[0]; - buf[j*4+1]=fontColor[1]; - buf[j*4+2]=fontColor[2]; + 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]; } @@ -267,8 +267,8 @@ namespace ui { * Get the width and height of the rendered character. */ - c1={x+ftexbl[c-33].x, - y+ftexbl[c-33].y}; + c1={(float)floor(x)+ftexbl[c-33].x, + (float)floor(y)+ftexbl[c-33].y}; c2=ftexwh[c-33]; /* @@ -316,7 +316,10 @@ namespace ui { if(s[i] == ' ') i++; } - if(s[i] == '\n' || s[i] == '\r' || s[i] == '\t'){ + if(s[i] == '\n'){ + yo-=fontSize*1.05; + xo=x; + }else if(s[i] == '\r' || s[i] == '\t'){ /*if(s[i] == '\n'){ yo-=fontSize*1.05; xo=x; @@ -325,7 +328,7 @@ namespace ui { }else if(s[i]=='\b'){ // Handle backspaces? xo-=add.x; }else{ - add=putChar(xo,yo,s[i]); + add=putChar(floor(xo),floor(yo),s[i]); xo+=add.x; yo+=add.y; } @@ -351,7 +354,7 @@ namespace ui { } }while(s[++i]); - putString(x-width/2,y,s); + putString(floor(x-width/2),y,s); return width; } @@ -528,15 +531,15 @@ namespace ui { } void importantText(const char *text,...){ va_list textArgs; - + //if(!player->ground)return; - + memset(dialogBoxText,0,512); - + va_start(textArgs,text); vsnprintf(dialogBoxText,512,text,textArgs); va_end(textArgs); - + dialogBoxExists = true; dialogImportant = true; //toggleBlack(); @@ -628,13 +631,13 @@ namespace ui { if(player->inv->invOpen){ hub.y = player->loc.y + fontSize * 8; - hub.x = player->loc.x; + hub.x = player->loc.x;// + player->width / 2; putStringCentered(hub.x,hub.y,"Current Quests:"); for(auto &c : player->qh.current){ hub.y -= fontSize * 1.15; - putString(hub.x,hub.y,c.title.c_str()); + putStringCentered(hub.x,hub.y,c.title.c_str()); } } } @@ -727,7 +730,7 @@ namespace ui { */ void drawMenu(Menu *menu){ - setFontSize(18); + setFontSize(24); SDL_Event e; mouse.x=premouse.x+offset.x-(SCREEN_WIDTH/2); diff --git a/xml/playerSpawnHill1.xml b/xml/playerSpawnHill1.xml index a99b274..c5e736b 100644 --- a/xml/playerSpawnHill1.xml +++ b/xml/playerSpawnHill1.xml @@ -9,11 +9,8 @@ <trigger x="-300" id="Test" /> <npc name="Ralph" hasDialog="true" /> - <npc name="Johnny" hasDialog="true" /> - <structure type="5" inside="playerSpawnHill1_Building1.xml"/> - <village> - - </village> + <npc name="Johnny" hasDialog="false" /> + <structure type="5" inside="playerSpawnHill1_Building1.xml" /> </World> @@ -24,30 +21,39 @@ And it wasn't stormy. <Dialog name="Ralph"> - <text id="0"> - Hello there! - <option text="Hello" nextid="1" /> - <option text="Frig" nextid="2" /> + <text id="0" nextid="1" > + Hello there! My name is Ralph. </text> - <text id="1"> - gg. + <text id="1" nextid="2" call="Johnny" callid="0" pause="true" > + You should go talk to my friend Johnny. He's a pretty chill dude. </text> +<<<<<<< HEAD <text id="2" call="Johnny" callid="1"> what you have done it to trick Microsoft? +======= + <text id="2" > + Niice. + <quest check="Your First Quest" fail="3" /> +>>>>>>> 3033594b89f23e65b6152daa6610f991307f2f67 </text> + <text id="3"> + Go check out Johnny. He's cool. + </text> </Dialog> <Dialog name="Johnny"> - <text id="0" nextid="1" pause="true"> - Sup bro! - <quest assign="Quest #1" /> + <text id="0" nextid="1" pause="true" > + Sup bro! Have a quest. To complete it, just go talk to Ralph again. + <quest assign="Your First Quest" > + Dank MayMay,2 + Wood Sword,1 + </quest> </text> - <text id="1" stop="true"> - My name's Johnny. - <give id="Dank Maymay" count="1" /> + <text id="1" nextid="1" pause="true" > + Broooooooooooooo... </text> </Dialog> diff --git a/xml/playerSpawnHill1_Building1.xml b/xml/playerSpawnHill1_Building1.xml index 54d217b..67695c7 100644 --- a/xml/playerSpawnHill1_Building1.xml +++ b/xml/playerSpawnHill1_Building1.xml @@ -3,6 +3,32 @@ <style background="1" bgm="assets/music/theme_jazz.wav" /> <generation type="Random" width="300" /> - <npc name="Bob" /> + <npc name="Bob" hasDialog="true" /> </IndoorWorld> + +<Dialog name="Bob"> + <text id="0" nextid="1" pause="true"> + Hey. Have a Dank MayMay :) + <give id="Dank MayMay" count="1" /> + </text> + + <text id="1" nextid="2"> + What? You want another Dank MayMay? + </text> + + <text id="2" nextid="3" pause="true"> + K. + <give id="Dank MayMay" count="1" /> + </text> + + <text id="3" nextid="4"> + Well... I'm out of Dank MayMays. + </text> + + <text id="4"> + Have a sword though. + <give id="Wood Sword" count="1" /> + </text> + +</Dialog> |