aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordrumsetmonkey <abelleisle@roadrunner.com>2016-02-11 08:28:27 -0500
committerdrumsetmonkey <abelleisle@roadrunner.com>2016-02-11 08:28:27 -0500
commit2a4a514b654ef0e08134a116c658d49a8f16cfe7 (patch)
tree8f33af3d9508c370a27719d3bc2089ada1abeffb
parenta0afc9a192016b2bb4c185895a4082cc965e1179 (diff)
parent3033594b89f23e65b6152daa6610f991307f2f67 (diff)
Worlds can be themed
-rw-r--r--Changelog22
-rw-r--r--config/items.xml2
-rw-r--r--config/settings.xml.example26
-rw-r--r--include/Quest.h23
-rw-r--r--include/inventory.h1
-rw-r--r--src/Quest.cpp117
-rw-r--r--src/entities.cpp6
-rw-r--r--src/gameplay.cpp37
-rw-r--r--src/inventory.cpp51
-rw-r--r--src/ui.cpp33
-rw-r--r--xml/playerSpawnHill1.xml40
-rw-r--r--xml/playerSpawnHill1_Building1.xml28
12 files changed, 254 insertions, 132 deletions
diff --git a/Changelog b/Changelog
index 2077ac0..582259c 100644
--- a/Changelog
+++ b/Changelog
@@ -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);
}
diff --git a/src/ui.cpp b/src/ui.cpp
index ead4932..e6ee988 100644
--- a/src/ui.cpp
+++ b/src/ui.cpp
@@ -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>