aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorClyne Sullivan <tullivan99@gmail.com>2016-04-23 22:31:27 -0400
committerClyne Sullivan <tullivan99@gmail.com>2016-04-23 22:31:27 -0400
commitcc2230e0039f06a7478878adcbc9ef028a223243 (patch)
tree1af80e53bc7f6ec6fa7c7d4f89656d61f203808f /src
parentdebb080a17eba2b2957e99ba7f1ce0fa0c4d2e4e (diff)
more rewrites
Diffstat (limited to 'src')
-rw-r--r--src/entities.cpp164
-rw-r--r--src/gameplay.cpp292
-rw-r--r--src/inventory.cpp11
-rw-r--r--src/ui.cpp50
-rw-r--r--src/ui_action.cpp6
-rw-r--r--src/world.cpp182
6 files changed, 332 insertions, 373 deletions
diff --git a/src/entities.cpp b/src/entities.cpp
index 96fe0e6..16ba768 100644
--- a/src/entities.cpp
+++ b/src/entities.cpp
@@ -1,6 +1,8 @@
+#include <entities.hpp>
+
#include <istream>
+#include <sstream>
-#include <entities.hpp>
#include <ui.hpp>
extern std::istream *names;
@@ -12,13 +14,15 @@ extern unsigned int tickCount; // main.cpp
extern std::string xmlFolder;
-GLuint waterTex;
-
-std::vector<int (*)(NPC *)> AIpreload; // A dynamic array of AI functions that are being preloaded
-std::vector<NPC *> AIpreaddr; // A dynamic array of pointers to the NPC's that are being assigned the preloads
+// a dynamic array of pointers to the NPC's that are being assigned the preloads
+std::vector<NPC *> aipreload;
-#define RAND_DIALOG_COUNT 14
+// 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 const unsigned int RAND_DIALOG_COUNT = 14;
const char *randomDialog[RAND_DIALOG_COUNT] = {
"What a beautiful day it is.",
"Have you ever went fast? I have.",
@@ -36,11 +40,8 @@ const char *randomDialog[RAND_DIALOG_COUNT] = {
"What's a bagel? I don't know because I'm mormon"
};
-void initEntity() {
- waterTex = Texture::loadTexture("assets/waterTex.png");
-}
-
-void getRandomName(Entity *e) {
+void getRandomName(Entity *e)
+{
unsigned int tempNum,max=0;
char *bufs;
@@ -76,17 +77,9 @@ void getRandomName(Entity *e) {
delete[] bufs;
}
-Trade::Trade(int qo, std::string o, int qt, std::string t) {
- item[0] = o;
- item[1] = t;
-
- quantity[0] = qo;
- quantity[1] = qt;
-
- std::cout << "Trading: " << quantity[0] << " " << item[0] << " for " << quantity[1] << " " << item[1] << std::endl;
-}
-
-void Entity::spawn(float x, float y) { //spawns the entity you pass to it based off of coords and global entity settings
+// 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;
vel.x = 0;
@@ -99,7 +92,6 @@ void Entity::spawn(float x, float y) { //spawns the entity you pass to it based
near = false;
//canMove = true;
ground = false;
- hit = false;
forcedMove = false;
ticksToUse = 0;
@@ -122,7 +114,52 @@ void Entity::spawn(float x, float y) { //spawns the entity you pass to it based
followee = NULL;
}
-Player::Player() { //sets all of the player specific traits on object creation
+void Entity::takeHit(unsigned int _health, unsigned int cooldown)
+{
+ // modify variables
+ health = fmax(health - _health, 0);
+ forcedMove = true;
+ hitCooldown = cooldown;
+
+ // pushback
+ vel.x = player->left ? -0.5f : 0.5f;
+ vel.y = 0.2f;
+}
+
+void Entity::handleHits(void)
+{
+ 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;
+}
+
+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(){ //sets all of the player specific traits on object creation
width = HLINE * 10;
height = HLINE * 16;
@@ -168,11 +205,8 @@ NPC::NPC() { //sets all of the NPC specific traits on object creation
dialogIndex = 0;
}
-NPC::~NPC() {
- while(!aiFunc.empty()) {
- aiFunc.pop_back();
- }
-
+NPC::~NPC()
+{
delete inv;
delete tex;
delete[] name;
@@ -268,6 +302,7 @@ Mob::Mob(int sub) {
inv = new Inventory(NPC_INV_SIZE);
}
+
Mob::~Mob() {
delete inv;
delete tex;
@@ -322,23 +357,30 @@ bool Entity::isNear(Entity e) {
return pow(e.loc.x - loc.x, 2) + pow(e.loc.y - loc.y, 2) <= pow(40 * HLINE, 2);
}
-void Entity::draw(void) { //draws the entities
+void NPC::drawThingy(void) const
+{
+ if (dialogCount) {
+ auto w = width / 3;
+ glColor3ub(255, 255, 0);
+ glRectf(loc.x + w, loc.y + height, loc.x + w * 2, loc.y + height + w);
+ }
+}
+
+void Entity::draw(void)
+{
glPushMatrix();
glColor3ub(255,255,255);
if (!alive)
return;
- if (type==NPCT) {
- if (NPCp(this)->aiFunc.size()) {
- glColor3ub(255,255,0);
- glRectf(loc.x+width/3,loc.y+height,loc.x+width*2/3,loc.y+height+width/3);
- }
- if (gender == MALE) {
- glColor3ub(255,255,255);
- }else if (gender == FEMALE) {
- glColor3ub(255,105,180);
- }
+ if (type == NPCT) {
+ NPCp(this)->drawThingy();
+
+ if (gender == MALE)
+ glColor3ub(255, 255, 255);
+ else if (gender == FEMALE)
+ glColor3ub(255, 105, 180);
}
if (left) {
glScalef(-1.0f,1.0f,1.0f);
@@ -467,37 +509,31 @@ wander(int timeRun)
ticksToUse--;
}
-void NPC::addAIFunc(int (*func)(NPC *),bool preload) {
- if (preload) { // Preload AI functions so that they're given after
- // the current dialog box is closed
- AIpreload.push_back(func);
- AIpreaddr.push_back(this);
- }
- else aiFunc.push_back(func);
+void NPC::addAIFunc(bool preload)
+{
+ if (preload)
+ aipreload.push_back(this);
+ else
+ ++dialogCount;
}
-void NPC::clearAIFunc(void) {
- aiFunc.clear();
-}
+extern int commonAIFunc(NPC *speaker);
void NPC::interact() { //have the npc's interact back to the player
std::thread([this]{
- int (*func)(NPC *);
loc.y += 5;
canMove=false;
left = (player->loc.x < loc.x);
right = !left;
- if (aiFunc.size()) {
- func=aiFunc.front();
-
- if (!func(this)) {
- if (aiFunc.size())aiFunc.erase(aiFunc.begin());
- }
- }else{
- ui::dialogBox(name,NULL,false,randomDialog[randDialog]);
+ if (dialogCount && dialogIndex != 9999) {
+ if (!commonAIFunc(this))
+ dialogCount--;
+ } else {
+ ui::dialogBox(name, "", false, randomDialog[randDialog]);
}
+
ui::waitForDialog();
canMove=true;
}).detach();
@@ -588,8 +624,8 @@ void Merchant::interact() {
void Object::interact(void) {
std::thread([this]{
- if (questObject && alive) {
- ui::dialogBox(player->name, ":Yes:No", false, pickupDialog.c_str());
+ if(questObject && alive){
+ ui::dialogBox(player->name, ":Yes:No", false, pickupDialog);
ui::waitForDialog();
if (ui::dialogOptChosen == 1) {
player->inv->addItem(iname, 1);
@@ -763,10 +799,10 @@ void Player::save(void) {
for(auto &i : inv->items)
data.append(std::to_string((int)i.count) + "\n" + std::to_string((int)i.id) + "\n");
- data.append((std::string)(currentXML.c_str() + 4) + "\n");
+ data.append(std::string(currentXML.data() + 4) + "\n");
data.append("dOnE\0");
- out.write(data.c_str(),data.size());
+ out.write(data.data(),data.size());
out.close();
}
@@ -810,7 +846,7 @@ void Player::sspawn(float x,float y) {
}
std::getline(data,ddata);
- currentWorld = loadWorldFromXMLNoSave(ddata.c_str());
+ currentWorld = loadWorldFromXMLNoSave(ddata);
in.close();
}
diff --git a/src/gameplay.cpp b/src/gameplay.cpp
index e314be4..603ede7 100644
--- a/src/gameplay.cpp
+++ b/src/gameplay.cpp
@@ -14,10 +14,9 @@ extern Menu optionsMenu;
extern std::string xmlFolder;
-extern void mainLoop(void); // main.cpp
+extern std::vector<NPC *> aipreload;
-extern std::vector<NPC *> AIpreaddr; // entities.cpp
-extern std::vector<int (*)(NPC *)> AIpreload; // entities.cpp
+extern void mainLoop(void); // main.cpp
std::vector<XMLElement *> dopt;
@@ -27,197 +26,154 @@ inline void segFault() {
(*((int *)NULL))++;
}
-int commonAIFunc(NPC *speaker) {
+int commonAIFunc(NPC *speaker)
+{
XMLDocument xml;
XMLElement *exml,*oxml;
static unsigned int oldidx = 9999;
- const char *name;
+ std::string name;
unsigned int idx = 0;
bool stop = false;
- /*
- * Load the current world's XML file into memory for reading.
- */
-
+ // load the XML file and find the dialog tags
xml.LoadFile(currentXML.c_str());
exml = xml.FirstChildElement("Dialog");
- /*
- * Search for the correct dialog block.
- */
-
- while(strcmp(exml->Attribute("name"),speaker->name))
+ // search for the dialog block associated with this npc
+ while (exml->StrAttribute("name") != speaker->name)
exml = exml->NextSiblingElement();
+ // search for the desired text block
exml = exml->FirstChildElement();
-
- /*
- * Search for which text block should be used.
- */
-
- do{
- if (!strcmp(exml->Name(),"text")) {
- if (exml->UnsignedAttribute("id") == (unsigned)speaker->dialogIndex) {
-
- /*
- * Handle any quest tags
- */
-
- if ((oxml = exml->FirstChildElement("quest"))) {
- std::string qname;
-
- while (oxml) {
- if (!(qname = oxml->StrAttribute("assign")).empty())
- player->qh.assign(qname,"None",(std::string)oxml->GetText());
- else if (!(qname = oxml->StrAttribute("check")).empty()) {
- 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.
- */
-
- if ((oxml = exml->FirstChildElement("give"))) {
- while(oxml) {
- player->inv->addItem(oxml->Attribute("id"),oxml->UnsignedAttribute("count"));
- oxml = oxml->NextSiblingElement();
- }
- }
-
- /*
- * Handle any 'take' requests.
- */
-
- if ((oxml = exml->FirstChildElement("take"))) {
- while(oxml) {
- player->inv->takeItem(oxml->Attribute("id"),oxml->UnsignedAttribute("count"));
- oxml = oxml->NextSiblingElement();
- }
+ std::cout << speaker->dialogIndex << '\n';
+ do {
+ if (std::string("text") == exml->Name() && exml->UnsignedAttribute("id") == (unsigned)speaker->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, "None", std::string(oxml->GetText())); // TODO add descriptions
+
+ // 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 = speaker->dialogIndex;
+ speaker->dialogIndex = oxml->UnsignedAttribute("fail");
+ return commonAIFunc(speaker);
}
+ }
+ } while((oxml = oxml->NextSiblingElement()));
+ }
- /*
- * Handle 'go to' thingy
- */
-
- if ((oxml = exml->FirstChildElement("gotox")))
- speaker->targetx = atoi(oxml->GetText());
-
- /*
- * Handle dialog options.
- */
-
- if ((oxml = exml->FirstChildElement("option"))) {
-
- /*
- * Convert the list of options into a single colon-separated string.
- */
-
- std::string optstr;
+ // handle give tags
+ if ((oxml = exml->FirstChildElement("give"))) {
+ do player->inv->addItem(oxml->Attribute("id"), oxml->UnsignedAttribute("count"));
+ while ((oxml = oxml->NextSiblingElement()));
+ }
- while(oxml) {
+ // handle take tags
+ if ((oxml = exml->FirstChildElement("take"))) {
+ do player->inv->takeItem(oxml->Attribute("id"), oxml->UnsignedAttribute("count"));
+ while ((oxml = oxml->NextSiblingElement()));
+ }
- /*
- * Create a buffer big enough for the next option.
- */
+ // handle movement directs
+ if ((oxml = exml->FirstChildElement("gotox")))
+ speaker->moveTo(std::stoi(oxml->GetText()));
- optstr.append((std::string)":" + oxml->Attribute("text"));
+ // handle dialog options
+ if ((oxml = exml->FirstChildElement("option"))) {
+ std::string optstr;
- /*
- * Append the next option.
- */
+ // convert option strings to a colon-separated format
+ do {
+ // append the next option
+ optstr.append(std::string(":") + oxml->Attribute("text"));
- dopt.push_back(oxml);
+ // save the associated XMLElement
+ dopt.push_back(oxml);
+ } while ((oxml = oxml->NextSiblingElement()));
- oxml = oxml->NextSiblingElement();
- }
+ // run the dialog stuff
+ ui::dialogBox(speaker->name, optstr, false, exml->GetText() + 1);
+ ui::waitForDialog();
- /*
- * Get the player's choice, then set the XMLElement to the option's block.
- */
+ if (ui::dialogOptChosen)
+ exml = dopt[ui::dialogOptChosen - 1];
- ui::dialogBox(speaker->name,optstr.c_str(),false,exml->GetText()+1);
- ui::waitForDialog();
+ dopt.clear();
+ }
- if (ui::dialogOptChosen)
- exml = dopt[ui::dialogOptChosen-1];
+ // optionless dialog
+ else {
+ ui::dialogBox(speaker->name, "", false, exml->GetText());
+ ui::waitForDialog();
+ }
- while(!dopt.empty())
- dopt.pop_back();
- }else{
+ // trigger other npcs if desired
+ if (!(name = exml->StrAttribute("call")).empty()) {
+ NPC *n = *std::find_if(std::begin(currentWorld->npc), std::end(currentWorld->npc), [name](NPC *npc) {
+ return (npc->name == name);
+ });
- /*
- * No options - simply print the text.
- */
+ if (exml->QueryUnsignedAttribute("callid", &idx) == XML_NO_ERROR) {
+ n->dialogIndex = idx;
+ n->addAIFunc(false);
+ }
+ }
- ui::dialogBox(speaker->name,NULL,false,exml->GetText());
- ui::waitForDialog();
- }
+ // handle potential following dialogs
+ if ((idx = exml->UnsignedAttribute("nextid"))) {
+ speaker->dialogIndex = idx;
- /*
- * Give another NPC dialog if requested.
- */
-
- if ((name = exml->Attribute("call"))) {
- for(auto &n : currentWorld->npc) {
- if (!strcmp(n->name,name)) {
- if (exml->QueryUnsignedAttribute("callid",&idx) == XML_NO_ERROR)
- n->dialogIndex = idx;
- n->addAIFunc(commonAIFunc,false);
- break;
- }
- }
- }
+ // stop talking
+ if (exml->QueryBoolAttribute("stop", &stop) == XML_NO_ERROR && stop) {
+ speaker->dialogIndex = 9999;
+ return 0;
+ }
- /*
- * Handle the next dialog block if this one leads to another.
- */
-
- if (exml->QueryUnsignedAttribute("nextid",&idx) == XML_NO_ERROR) {
- speaker->dialogIndex = idx;
-
- if (exml->QueryBoolAttribute("stop",&stop) == XML_NO_ERROR && stop) {
- speaker->dialogIndex = 9999;
- return 0;
- }else if (exml->QueryBoolAttribute("pause",&stop) == XML_NO_ERROR && stop) {
- //speaker->dialogIndex = 9999;
- return 1;
- }else return commonAIFunc(speaker);
- }else{
- if (oldidx != 9999) {
- speaker->dialogIndex = oldidx;
- oldidx = 9999;
- return 1;
- }else{
- speaker->dialogIndex = 9999;
- return 0;
- }
- }
- //return 1;
- }
+ // pause, allow player to click npc to continue
+ else if (exml->QueryBoolAttribute("pause", &stop) == XML_NO_ERROR && stop) {
+ return 1;
}
- exml = exml->NextSiblingElement();
+ // instantly continue
+ else {
+ return commonAIFunc(speaker);
+ }
+ }
- }while(exml);
+ // stop talking
+ else {
+ // error text?
+ if (oldidx != 9999) {
+ speaker->dialogIndex = oldidx;
+ oldidx = 9999;
+ return 1;
+ } else {
+ speaker->dialogIndex = 9999;
+ return 0;
+ }
+ }
return 0;
}
-void commonPageFunc(Mob *callee) {
+void commonPageFunc(Mob *callee)
+{
ui::drawPage(callee->heyid);
ui::waitForDialog();
callee->health = 0;
@@ -235,7 +191,7 @@ void commonTriggerFunc(Mob *callee) {
xml.LoadFile(currentXML.c_str());
exml = xml.FirstChildElement("Trigger");
- while(strcmp(exml->Attribute("id"),callee->heyid.c_str()))
+ while(exml->StrAttribute("id") != callee->heyid)
exml = exml->NextSiblingElement();
player->vel.x = 0;
@@ -284,16 +240,11 @@ void initEverything(void) {
* Load the first file found as currentWorld.
*/
- for(unsigned int i=0;i<xmlFiles.size();i++) {
- if (xmlFiles[i] != "." && xmlFiles[i] != ".." && strcmp(xmlFiles[i].c_str()+xmlFiles[i].size()-3,"dat")) {
-
- /*
- * Read in the XML file.
- */
- C("Setting current XML file");
- std::cout << "File to load: " << xmlFiles[i] << std::endl;
- currentWorld = loadWorldFromXML(xmlFiles[i]);
- C("Done setting current XML file");
+ for (xf : xmlFiles) { //unsigned int i=0;i<xmlFiles.size();i++){
+ if (xf[0] != '.' && strcmp(&xf[xf.size() - 3], "dat")){
+ // read the xml file
+ std::cout << "File to load: " << xf << std::endl;
+ currentWorld = loadWorldFromXML(xf);
break;
}
}
@@ -326,8 +277,5 @@ void destroyEverything(void) {
//delete currentWorld;
//delete[] currentXML;
- while(!AIpreload.empty())
- AIpreload.pop_back();
- while(!AIpreaddr.empty())
- AIpreaddr.pop_back();
+ aipreload.clear();
}
diff --git a/src/inventory.cpp b/src/inventory.cpp
index c6b28d9..4cf5fda 100644
--- a/src/inventory.cpp
+++ b/src/inventory.cpp
@@ -150,8 +150,9 @@ void destroyInventory(void) {
Mix_FreeChunk(swordSwing);
}
-const char *getItemTexturePath(std::string name) {
- for(auto &i : itemMap) {
+
+const char *getItemTexturePath(std::string name){
+ for (auto &i : itemMap) {
if (i->name == name)
return i->texloc.c_str();
}
@@ -397,7 +398,7 @@ void Inventory::draw(void) {
glEnd();
glDisable(GL_TEXTURE_2D);
ui::setFontColor(255,255,255,((float)dfp[a]/(float)(range?range:1))*255);
- ui::putStringCentered(r.end.x,r.end.y-(itemWide*.9),itemMap[items[a].id]->name.c_str());
+ ui::putStringCentered(r.end.x,r.end.y-(itemWide*.9),itemMap[items[a].id]->name);
ui::putText(r.end.x-(itemWide/2)+(itemWide*.85),r.end.y-(itemWide/2),"%d",items[a].count);
ui::setFontColor(255,255,255,255);
}
@@ -518,8 +519,8 @@ void Inventory::draw(void) {
if (highlight < items.size()) {
ui::putStringCentered(player->loc.x + player->width / 2,
player->loc.y + range * 0.75f,
- itemMap[items[highlight].id]->name.c_str()
- );
+ itemMap[items[highlight].id]->name
+ );
}
}
if (!items.empty() && items.size() > sel && items[sel].count)
diff --git a/src/ui.cpp b/src/ui.cpp
index 59ea102..30d08a2 100644
--- a/src/ui.cpp
+++ b/src/ui.cpp
@@ -20,9 +20,7 @@ extern WorldWeather weather;
* In the case of dialog, some NPC quests can be preloaded so that they aren't assigned until
* the dialog box closes. Reference variables for that here.
*/
-
-extern std::vector<int (*)(NPC *)> AIpreload;
-extern std::vector<NPC *> AIpreaddr;
+extern std::vector<NPC *> aipreload;
/*
* Pressing ESC or closing the window will set this to false.
@@ -463,20 +461,19 @@ namespace ui {
return putString(x, y, buf.get());
}
- void dialogBox(const char *name, const char *opt, bool passive, const char *text, ...) {
+ void dialogBox(std::string name, std::string opt, bool passive, std::string text, ...) {
va_list dialogArgs;
std::unique_ptr<char[]> printfbuf (new char[512]);
textWrapLimit = 110;
dialogPassive = passive;
- // reset & add speaker prefix
- dialogBoxText.clear();
- dialogBoxText = (std::string)name + ": ";
+ // add speaker prefix
+ dialogBoxText = name + ": ";
// handle the formatted string
- va_start(dialogArgs,text);
- vsnprintf(printfbuf.get(),512,text,dialogArgs);
+ va_start(dialogArgs, text);
+ vsnprintf(printfbuf.get(), 512, text.c_str(), dialogArgs);
va_end(dialogArgs);
dialogBoxText += printfbuf.get();
@@ -485,12 +482,11 @@ namespace ui {
dialogOptChosen = 0;
- if (opt) {
- std::string soptbuf = opt;
- char *sopt = strtok(&soptbuf[0], ":");
+ if (!opt.empty()) {
+ char *sopt = strtok(&opt[0], ":");
// cycle through options
- while(sopt) {
+ while (sopt) {
dialogOptText.push_back(std::make_pair((std::string)sopt, vec3 {0,0,0}));
sopt = strtok(NULL,":");
}
@@ -558,11 +554,11 @@ namespace ui {
* Wait for a dialog box to be dismissed.
*/
- void waitForDialog (void) {
+ void waitForDialog(void) {
while (dialogBoxExists);
}
- void waitForCover (void) {
+ void waitForCover(void) {
while (fadeIntensity < 255)
mainLoop();
fadeIntensity = 255;
@@ -666,7 +662,7 @@ namespace ui {
}
if (fadeIntensity == 255 || dialogPassive) {
setFontSize(24);
- putStringCentered(offset.x,offset.y,rtext.c_str());
+ putStringCentered(offset.x,offset.y,rtext);
setFontSize(16);
}
}else if (dialogMerchant) {
@@ -683,10 +679,10 @@ namespace ui {
vec2 merchBase = {offset.x, offset.y + SCREEN_HEIGHT / 5};
- putStringCentered(merchBase.x + SCREEN_WIDTH / 10 - 20, merchBase.y + 40 + fontSize * 2, itemString1.c_str());
- putStringCentered(merchBase.x + SCREEN_WIDTH / 10 - 20, merchBase.y + 40 + fontSize , merchTrade.item[0].c_str());
- putStringCentered(merchBase.x - SCREEN_WIDTH / 10 , merchBase.y + 40 + fontSize * 2, itemString2.c_str());
- putStringCentered(merchBase.x - SCREEN_WIDTH / 10 , merchBase.y + 40 + fontSize , merchTrade.item[1].c_str());
+ 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");
glEnable(GL_TEXTURE_2D);
@@ -797,7 +793,7 @@ namespace ui {
putText(hub.x,hub.y,"Health: %u/%u",player->health>0?(unsigned)player->health:0,
(unsigned)player->maxHealth
);
- if (player->alive) {
+ if (player->isAlive()) {
glColor3ub(150,0,0);
hub.y-=fontSize*1.15;
glRectf(hub.x,
@@ -824,7 +820,7 @@ namespace ui {
for(auto &c : player->qh.current) {
hub.y -= fontSize * 1.15;
- putStringCentered(hub.x,hub.y,c.title.c_str());
+ putStringCentered(hub.x,hub.y,c.title);
}
hub.y = offset.y + 40*1.2;
@@ -899,6 +895,7 @@ EXIT:
//if (!dialogMerchant)closeBox();
dialogBoxExists = false;
dialogMerchant = false;
+ dialogPassive = false;
//DONE:
@@ -1211,11 +1208,10 @@ EXIT:
}
// Flush preloaded AI functions if necessary
- if (!dialogBoxExists && AIpreaddr.size()) {
- while (!AIpreaddr.empty()) {
- AIpreaddr.front()->addAIFunc(AIpreload.front(), false);
- AIpreaddr.erase(AIpreaddr.begin());
- AIpreload.erase(AIpreload.begin());
+ if (!dialogBoxExists) {
+ while (!aipreload.empty()) {
+ aipreload.front()->addAIFunc(false);
+ aipreload.erase(std::begin(aipreload));
}
}
}
diff --git a/src/ui_action.cpp b/src/ui_action.cpp
index a7bb36b..264100d 100644
--- a/src/ui_action.cpp
+++ b/src/ui_action.cpp
@@ -137,10 +137,8 @@ void actionAction(void)
auto e = currentWorld->getNearInteractable(*player);
- if (e->type == NPCT) {
- if (!NPCp(e)->aiFunc.empty())
- e->interact();
- }
+ if (e->type == NPCT)
+ e->interact();
ACTION_EPILOUGE;
}
diff --git a/src/world.cpp b/src/world.cpp
index 5893bfb..37d899d 100644
--- a/src/world.cpp
+++ b/src/world.cpp
@@ -190,9 +190,6 @@ deleteEntities(void)
void World::
generate(unsigned int width)
{
- // iterator for `for` loops
- std::vector<WorldData>::iterator wditer;
-
// see below for description/usage
float geninc = 0;
@@ -206,34 +203,24 @@ generate(unsigned int width)
// prepare for generation
worldData.front().groundHeight = GROUND_HEIGHT_INITIAL;
- wditer = worldData.begin();
+ auto wditer = std::begin(worldData) + GROUND_HILLINESS;
// give every GROUND_HILLINESSth entry a groundHeight value
- for (unsigned i = GROUND_HILLINESS; i < worldData.size(); i += GROUND_HILLINESS, wditer += GROUND_HILLINESS)
- worldData[i].groundHeight = (*wditer).groundHeight + (randGet() % 8 - 4);
+ for (; wditer < std::end(worldData); wditer += GROUND_HILLINESS)
+ (*(wditer - GROUND_HILLINESS)).groundHeight = (*wditer).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++){
+ auto w = &*(wditer);
- for(wditer = worldData.begin() + 1; wditer != worldData.end(); wditer++) {
- if ((*wditer).groundHeight && wditer + GROUND_HILLINESS < worldData.end())
- // wditer + GROUND_HILLINESS can go out of bounds (invalid read)
- geninc = ((*(wditer + GROUND_HILLINESS)).groundHeight - (*wditer).groundHeight) / (float)GROUND_HILLINESS;
- else {
- (*wditer).groundHeight = (*(wditer - 1)).groundHeight + geninc;
-
- if ((*wditer).groundHeight < GROUND_HEIGHT_MINIMUM)
- (*wditer).groundHeight = GROUND_HEIGHT_MINIMUM;
- else if ((*wditer).groundHeight > GROUND_HEIGHT_MAXIMUM)
- (*wditer).groundHeight = GROUND_HEIGHT_MAXIMUM;
- }
-
- (*wditer).groundColor = randGet() % 32 / 8;
- (*wditer).grassUnpressed = true;
- (*wditer).grassHeight[0] = (randGet() % 16) / 3 + 2;
- (*wditer).grassHeight[1] = (randGet() % 16) / 3 + 2;
+ if (w->groundHeight)
+ geninc = ((w + (int)GROUND_HILLINESS)->groundHeight - w->groundHeight) / GROUND_HILLINESS;
- if((*wditer).groundHeight <= 0)
- (*wditer).groundHeight = GROUND_HEIGHT_MINIMUM;
+ w->groundHeight = fmin(fmax((w - 1)->groundHeight + geninc, GROUND_HEIGHT_MINIMUM), GROUND_HEIGHT_MAXIMUM);
+ w->groundColor = randGet() % 32 / 8;
+ w->grassUnpressed = true;
+ w->grassHeight[0] = (randGet() % 16) / 3 + 2;
+ w->grassHeight[1] = (randGet() % 16) / 3 + 2;
}
// define x-coordinate of world's leftmost 'line'
@@ -449,22 +436,21 @@ draw(Player *p)
glBegin(GL_QUADS);
//std::for_each(std::begin(worldData) + iStart, std::begin(worldData) + iEnd, [&](WorldData wd) {
for (i = iStart; i < iEnd; i++) {
- auto wd = worldData[i];
- if (wd.groundHeight <= 0) {
- wd.groundHeight = GROUND_HEIGHT_MINIMUM - 1;
+ if (worldData[i].groundHeight <= 0) {
+ worldData[i].groundHeight = GROUND_HEIGHT_MINIMUM - 1;
glColor4ub(0, 0, 0, 255);
} else {
safeSetColorA(150, 150, 150, 255);
}
- int ty = wd.groundHeight / 64 + wd.groundColor;
- glTexCoord2i(0, 0); glVertex2i(worldStart + i * HLINE , wd.groundHeight - GRASS_HEIGHT);
- glTexCoord2i(1, 0); glVertex2i(worldStart + i * HLINE + HLINE , wd.groundHeight - GRASS_HEIGHT);
+ int ty = worldData[i].groundHeight / 64 + worldData[i].groundColor;
+ glTexCoord2i(0, 0); glVertex2i(worldStart + i * HLINE , worldData[i].groundHeight - GRASS_HEIGHT);
+ glTexCoord2i(1, 0); glVertex2i(worldStart + i * HLINE + HLINE , worldData[i].groundHeight - GRASS_HEIGHT);
glTexCoord2i(1, ty); glVertex2i(worldStart + i * HLINE + HLINE, 0);
glTexCoord2i(0, ty); glVertex2i(worldStart + i * HLINE , 0);
- if (wd.groundHeight == GROUND_HEIGHT_MINIMUM - 1)
- wd.groundHeight = 0;
+ if (worldData[i].groundHeight == GROUND_HEIGHT_MINIMUM - 1)
+ worldData[i].groundHeight = 0;
}//);
glEnd();
@@ -558,10 +544,11 @@ singleDetect(Entity *e)
int l;
// kill dead entities
- if (e->alive && e->health <= 0) {
+ if (!e->isAlive()) {
+ return;
+ } else if (e->health <= 0) {
// die
- e->alive = false;
- e->health = 0;
+ e->die();
// delete the entity
for (i = 0; i < entity.size(); i++) {
@@ -599,15 +586,10 @@ singleDetect(Entity *e)
}
// collision / gravity: handle only living entities
- if (e->alive) {
+ else {
// forced movement gravity (sword hits)
- if (e->forcedMove) {
- if (e->vel.x > .0005 || e->vel.x < -.0005)
- e->vel.x *= .6;
- else
- e->forcedMove = false;
- }
+ e->handleHits();
if (e->subtype == MS_TRIGGER)
return;
@@ -877,7 +859,7 @@ void World::save(void){
for (auto &m : mob) {
data.append(std::to_string((int)m->loc.x) + "\n");
data.append(std::to_string((int)m->loc.y) + "\n");
- data.append(std::to_string((int)m->alive) + "\n");
+ data.append(std::to_string((int)m->isAlive()) + "\n");
}
// wrap up
@@ -898,9 +880,8 @@ void World::load(void){
for(auto &n : npc){
std::getline(iss,line);
if(line == "dOnE")return;
- if((n->dialogIndex = std::stoi(line)) != 9999)
- n->addAIFunc(commonAIFunc,false);
- else n->clearAIFunc();
+ if ((n->dialogIndex = std::stoi(line)) != 9999)
+ n->addAIFunc(false);
std::getline(iss,line);
if(line == "dOnE")return;
@@ -928,7 +909,8 @@ void World::load(void){
m->loc.y = std::stoi(line);
std::getline(iss,line);
if(line == "dOnE")return;
- m->alive = std::stoi(line);
+ if (!std::stoi(line))
+ m->die();
}
while(std::getline(iss,line)){
@@ -1005,18 +987,15 @@ setStyle(std::string pre)
// get folder prefix
std::string prefix = pre.empty() ? "assets/style/classic/" : pre;
- for_each(std::begin(buildPaths), std::end(buildPaths), [this, prefix](std::string s){
+ for (s : buildPaths)
sTexLoc.push_back(prefix + s);
- });
prefix += "bg/";
- for_each(std::begin(bgPaths[0]), std::end(bgPaths[0]), [this, prefix](std::string s){
+ for (s : bgPaths[0])
bgFiles.push_back(prefix + s);
- });
- for_each(std::begin(bgPaths[1]), std::end(bgPaths[1]), [this, prefix](std::string s){
+ for (s : bgPaths[1])
bgFilesIndoors.push_back(prefix + s);
- });
}
/**
@@ -1107,7 +1086,7 @@ goWorldLeft(NPC *e)
// check if entity is at world edge
if(!toLeft.empty() && e->loc.x < worldStart + HLINE * 15.0f) {
currentWorldToLeft->addNPC(e->loc.x,e->loc.y);
- e->alive = false;
+ e->die();
currentWorldToLeft->npc.back()->loc.x = 0;
currentWorldToLeft->npc.back()->loc.y = GROUND_HEIGHT_MAXIMUM;
@@ -1125,45 +1104,50 @@ World *World::
goInsideStructure(Player *p)
{
World *tmp;
- std::string current;
if (inside.empty()) {
- for (auto &b : build) {
- if (p->loc.x > b->loc.x && p->loc.x + p->width < b->loc.x + b->width) {
- if (b->inside.empty())
- return this;
+ auto d = std::find_if(std::begin(build), std::end(build), [p](const Structures *s) {
+ return ((p->loc.x > s->loc.x) && (p->loc.x + p->width < s->loc.x + s->width));
+ });
+ auto b = *d;
- // +size cuts folder prefix
- inside.push_back(currentXML.c_str() + xmlFolder.size());
- tmp = loadWorldFromXML(b->inside);
+ if ((d == std::end(build)) || b->inside.empty())
+ return this;
- // make the fade, as we let it fade back the worlds should be switched
- ui::toggleBlackFast();
- ui::waitForCover();
- ui::toggleBlackFast();
+ // +size cuts folder prefix
+ inside.push_back(&currentXML[xmlFolder.size()]);
+ tmp = loadWorldFromXML(b->inside);
- glClearColor(0, 0, 0, 1);
+ // make the fade, as we let it fade back the worlds should be switched
+ ui::toggleBlackFast();
+ ui::waitForCover();
+ ui::toggleBlackFast();
+ glClearColor(0, 0, 0, 1);
- return tmp;
- }
- }
+ return tmp;
} else {
- current = currentXML.c_str() + xmlFolder.size();
+ std::string current = &currentXML[xmlFolder.size()];
tmp = loadWorldFromXML(inside.back());
- for (auto &b : tmp->build) {
- if (current == b->inside) {
- inside.pop_back();
+ inside.clear();
- ui::toggleBlackFast();
- ui::waitForCover();
- p->loc.x = b->loc.x + (b->width / 2);
- ui::toggleBlackFast();
+ Structures *b;
+ for (auto &s : build) {
+ if (s->inside == current) {
+ b = s;
+ break;
+ }
+ }
+ //auto b = *std::find_if(std::begin(build), std::end(build), [&](const Structures *s) {
+ // return (s->inside == current);
+ //});
- glClearColor(1, 1, 1, 1);
+ ui::toggleBlackFast();
+ ui::waitForCover();
+ p->loc.x = b->loc.x + (b->width / 2);
+ ui::toggleBlackFast();
+ glClearColor(1, 1, 1, 1);
- return tmp;
- }
- }
+ return tmp;
}
return this;
@@ -1173,18 +1157,15 @@ void World::addStructure(BUILD_SUB sub, float x,float y, std::string tex, std::s
build.push_back(new Structures());
build.back()->inWorld = this;
build.back()->textureLoc = tex;
-
build.back()->spawn(sub,x,y);
-
build.back()->inside = inside;
-
entity.push_back(build.back());
}
Village *World::
addVillage(std::string name, World *world)
{
- village.emplace_back(name.c_str(), world);
+ village.emplace_back(name, world);
return &village.back();
}
@@ -1358,9 +1339,9 @@ singleDetect(Entity *e)
unsigned int floornum = 0;
float start, end;
- if (!e->alive)
+ if (!e->isAlive())
return;
- if (e->type == MOBT && Mobp(e)->subtype == MS_TRIGGER)
+ if (e->type == MOBT && e->subtype == MS_TRIGGER)
return;
for (; floornum < floor.size(); floornum++) {
@@ -1527,10 +1508,10 @@ Arena::~Arena(void) {
World *Arena::exitArena(Player *p) {
World *tmp;
- if (!mmob->alive &&
- p->loc.x + p->width / 2 > mob[0]->loc.x &&
- p->loc.x + p->width / 2 < mob[0]->loc.x + HLINE * 12) {
- tmp = battleNest.front();
+ if (!mmob->isAlive() &&
+ p->loc.x + p->width / 2 > mob[0]->loc.x &&
+ p->loc.x + p->width / 2 < mob[0]->loc.x + HLINE * 12) {
+ tmp = battleNest.front();
battleNest.erase(battleNest.begin());
inBattle = !battleNest.empty();
@@ -1541,7 +1522,7 @@ World *Arena::exitArena(Player *p) {
battleNestLoc.pop_back();
mob.clear();
- mmob->alive = false;
+ mmob->die();
return tmp;
}else{
@@ -1749,9 +1730,9 @@ loadWorldFromXMLNoSave(std::string path) {
// dialog enabling
dialog = false;
- if (wxml->QueryBoolAttribute("hasDialog", &dialog) == XML_NO_ERROR && dialog)
- tmp->npc.back()->addAIFunc(commonAIFunc, false);
- else
+ if (wxml->QueryBoolAttribute("hasDialog", &dialog) == XML_NO_ERROR && dialog) {
+ tmp->npc.back()->addAIFunc(false);
+ } else
tmp->npc.back()->dialogIndex = 9999;
if (Indoor && wxml->QueryUnsignedAttribute("floor", &flooor) == XML_NO_ERROR)
@@ -1855,8 +1836,6 @@ loadWorldFromXMLNoSave(std::string path) {
sxml->IntAttribute("quantity1"),
sxml->StrAttribute("item1")));
} else if (tag == "text") { //this is what the merchant says
- std::cout << "text" << std::endl;
-
XMLElement *txml = sxml->FirstChildElement();
std::string textOption;
@@ -1894,7 +1873,7 @@ loadWorldFromXMLNoSave(std::string path) {
vil = vil->NextSiblingElement();
}
- std::ifstream dat (((std::string)currentXML + ".dat").c_str());
+ std::ifstream dat (((std::string)currentXML + ".dat").data());
if (dat.good()) {
dat.close();
tmp->load();
@@ -1903,7 +1882,8 @@ loadWorldFromXMLNoSave(std::string path) {
return tmp;
}
-Village::Village(const char *meme, World *w) {
+Village::Village(std::string meme, World *w)
+{
name = meme;
start.x = w->getTheWidth() / 2.0f;
end.x = -start.x;