From b22860234ff7991c851211042a9832d88ccbb958 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Tue, 31 May 2016 08:49:48 -0400 Subject: entitys can modify xml --- src/entities.cpp | 132 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 78 insertions(+), 54 deletions(-) (limited to 'src/entities.cpp') diff --git a/src/entities.cpp b/src/entities.cpp index 550748a..18c91ed 100644 --- a/src/entities.cpp +++ b/src/entities.cpp @@ -15,6 +15,7 @@ extern World *currentWorld; // main.cpp extern unsigned int loops; // main.cpp extern std::string xmlFolder; +extern XMLDocument currentXMLDoc; // a dynamic array of pointers to the NPC's that are being assigned the preloads std::vector aipreload; @@ -24,52 +25,17 @@ 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.", - "I heard if you complete a quest, you'll get a special reward.", - "How much wood could a woodchuck chuck if a woodchuck could chuck wood?", - "I don\'t think anyone has ever been able to climb up that hill.", - "If you ever see a hole in the ground, watch out; it could mean the end for you.", - "Did you know this game has over 5000 lines of code? I didn\'t. I didn't even know I was in a game until now...", - "HELP MY CAPS LOCK IS STUCK", - "You know, if anyone ever asked me who I wanted to be when I grow up, I would say Abby Ross.", - "I want to have the wallpaper in our house changed. It doesn\'t really fit the environment.", - "Frig.", - "The sine of theta equals the opposite over the hdaypotenuese.", - "Did you know the developers spelt brazier as brazzier.", - "What's a bagel? I don't know because I'm mormon" -}; - -void randGetomName(Entity *e) -{ - unsigned int tempNum,max=0; - char *bufs; - - std::ifstream names ("assets/names_en-us",std::ios::in); - - names.seekg(0,names.beg); - - bufs = new char[32]; - - for(;!names.eof();max++) - names.getline(bufs,32); +static std::vector randomDialog (readFileA("assets/dialog_en-us")); - tempNum = rand() % max; - names.seekg(0,names.beg); - - for(unsigned int i=0;igender = (bufs[0] == 'm') ? MALE : FEMALE; - - strcpy(e->name, bufs + 1); + e->gender = (name[0] == 'm') ? MALE : FEMALE; - delete[] bufs; + e->name = &name[1]; } Entity::Entity(void) @@ -101,7 +67,6 @@ Entity::Entity(void) hitDuration = maxHitDuration = 0; inv = nullptr; - name = nullptr; } // spawns the entity you pass to it based off of coords and global entity settings @@ -114,11 +79,10 @@ void Entity::spawn(float x, float y) health = maxHealth = 1; // generate a name - name = new char[32]; if (type == MOBT) - strncpy(name, "mob", 3); + name = "mob"; else - randGetomName(this); + getRandomName(this); setCooldown(0); } @@ -168,6 +132,11 @@ void Entity::die(void) { alive = false; health = 0; + + if (xmle) { + xmle->SetAttribute("alive", false); + currentXMLDoc.SaveFile(currentXML.c_str(), false); + } } bool Entity::isAlive(void) const @@ -218,7 +187,12 @@ Player::Player() : Entity() Player::~Player() { delete inv; - delete[] name; +} + +void Player::createFromXML(XMLElement *e, World *w=nullptr) +{ + (void)e; + (void)w; } NPC::NPC() : Entity() @@ -237,7 +211,7 @@ NPC::NPC() : Entity() tex = TextureIterator({"assets/NPC.png"}); inv = new Inventory(NPC_INV_SIZE); - randDialog = rand() % RAND_DIALOG_COUNT - 1; + randDialog = randGet() % randomDialog.size(); dialogIndex = 0; dialogCount = 0; @@ -249,7 +223,42 @@ NPC::NPC() : Entity() NPC::~NPC() { delete inv; - delete[] name; +} + +void NPC::createFromXML(XMLElement *e, World *w=nullptr) +{ + std::string npcname; + bool dialog; + float spawnx, Xhealth; + unsigned int flooor; + + // spawn at coordinates if desired + if (e->QueryFloatAttribute("x", &spawnx) == XML_NO_ERROR) + spawn(spawnx, 100); + else + spawn(0, 100); + + // name override + if (!(npcname = e->StrAttribute("name")).empty()) + name = npcname; + + // dialog enabling + dialog = false; + if (e->QueryBoolAttribute("hasDialog", &dialog) == XML_NO_ERROR && dialog) + addAIFunc(false); + else + dialogIndex = 9999; + + + if (/*Indoor && */e->QueryUnsignedAttribute("floor", &flooor) == XML_NO_ERROR) + Indoorp(w)->moveToFloor(this, flooor); + + // custom health value + if (e->QueryFloatAttribute("health", &Xhealth) == XML_NO_ERROR) { + health = maxHealth = Xhealth; + } + + xmle = e; } Merchant::Merchant() : NPC() @@ -283,8 +292,6 @@ Merchant::Merchant() : NPC() Merchant::~Merchant() { - //delete inv; - delete[] name; } Structures::Structures() : Entity() @@ -295,7 +302,19 @@ Structures::Structures() : Entity() Structures::~Structures() { - delete[] name; +} + +void Structures::createFromXML(XMLElement *e, World *w) +{ + float spawnx; + + inWorld = w; + inside = e->StrAttribute("inside"); + textureLoc = e->StrAttribute("texture"); + + spawn(static_cast(e->UnsignedAttribute("type")), + e->QueryFloatAttribute("x", &spawnx) == XML_NO_ERROR ? spawnx : (randGet() % w->getTheWidth() / 2.0f), + 100); } Object::Object() @@ -319,7 +338,12 @@ Object::Object(std::string in, std::string pd) Object::~Object() { - delete[] name; +} + +void Object::createFromXML(XMLElement *e, World *w=nullptr) +{ + (void)e; + (void)w; } void Object::reloadTexture(void) @@ -773,7 +797,7 @@ void Merchant::wander(int timeRun) { void Merchant::interact() { std::thread([this]{ - ui::merchantBox(name, trade[currTrade], ":Accept:Good-Bye", false, toSay->c_str()); + ui::merchantBox(name.c_str(), trade[currTrade], ":Accept:Good-Bye", false, toSay->c_str()); ui::waitForDialog(); // handle normal dialog options -- cgit v1.2.3 From 2e6369f4dbe2b49a3cb8bec3bacd6559c9733a55 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Thu, 2 Jun 2016 07:20:09 -0400 Subject: optimizations --- Makefile | 2 +- include/entities.hpp | 118 ++++++++++++++++++++++++----------------------- include/world.hpp | 2 +- main.cpp | 55 +++++++++++----------- src/entities.cpp | 14 ++++-- src/world.cpp | 45 +++++++++--------- xml/playerSpawnHill1.xml | 2 +- 7 files changed, 122 insertions(+), 116 deletions(-) (limited to 'src/entities.cpp') diff --git a/Makefile b/Makefile index 7c05c95..31899a5 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ ifeq ($(TARGET_OS),win32) -lSDL2main -lSDL2 -lSDL2_image -lSDL2_mixer -lfreetype endif -CXXFLAGS = -g -m$(TARGET_BITS) -std=c++14 +CXXFLAGS = -g -m$(TARGET_BITS) -std=c++14 -fext-numeric-literals CXXINC = -Iinclude -Iinclude/freetype CXXWARN = -Wall -Wextra -Werror #-pedantic-errors diff --git a/include/entities.hpp b/include/entities.hpp index 5a8e19b..61ecc43 100644 --- a/include/entities.hpp +++ b/include/entities.hpp @@ -106,64 +106,6 @@ extern const unsigned int NPC_INV_SIZE; // a prototype of the world class, necessary for some function prototypes class World; -/** - * The particle class, handles a single particle. - */ -class Particles{ -public: - // the location of the particle - vec2 loc; - float zOffset; - - // the width of the particle, in pixels - float width; - - // the height of the particle, in pixels - float height; - - // the velocity of the particle, in pixels - vec2 vel; - - // the color of the particle - Color color; - - // TODO - vec2 index; - - // the amount of milliseconds left for the particle to live - float duration; - - // when true, the particle will move - bool canMove; - - // TODO - bool fountain; - - // when true, the particle will be affected by gravity - bool gravity; - - // when true, draws the particle behind structures - bool behind; - - // when true, the particle will bounce on impact with ground - bool bounce; - - // creates a particle with the desired characteristics - Particles(float x, float y, float w, float h, float vx, float vy, Color c, float d); - - // allows the particle to be destroyed - ~Particles(void){} - - // draws the particle - void draw(GLfloat*& p) const; - - // updates a particle - void update(float _gravity, float ground_y); - - // returns true if the particle should be killed - bool kill(float delta); -}; - /** * The entity class. * This class contains common functions and variables for all types of @@ -433,6 +375,66 @@ public: void createFromXML(XMLElement *e); }; +/** + * The particle class, handles a single particle. + */ +class Particles{ +public: + // the location of the particle + vec2 loc; + float zOffset; + + // the width of the particle, in pixels + float width; + + // the height of the particle, in pixels + float height; + + // the velocity of the particle, in pixels + vec2 vel; + + // the color of the particle + Color color; + + // TODO + vec2 index; + + // the amount of milliseconds left for the particle to live + float duration; + + // when true, the particle will move + bool canMove; + + // TODO + bool fountain; + + // when true, the particle will be affected by gravity + bool gravity; + + // when true, draws the particle behind structures + bool behind; + + // when true, the particle will bounce on impact with ground + bool bounce; + + Structures *stu; + + // creates a particle with the desired characteristics + Particles(float x, float y, float w, float h, float vx, float vy, Color c, float d); + + // allows the particle to be destroyed + ~Particles(void){} + + // draws the particle + void draw(GLfloat*& p) const; + + // updates a particle + void update(float _gravity, float ground_y); + + // returns true if the particle should be killed + bool timeUp(void); +}; + #include constexpr Object *Objectp(Entity *e) { diff --git a/include/world.hpp b/include/world.hpp index f6a432d..2494120 100644 --- a/include/world.hpp +++ b/include/world.hpp @@ -256,7 +256,7 @@ protected: * * @see addParticle() */ - std::vector particles; + std::list particles; /** * A vector of all structures in the world. diff --git a/main.cpp b/main.cpp index dc586df..4cf0475 100644 --- a/main.cpp +++ b/main.cpp @@ -25,7 +25,7 @@ using namespace tinyxml2; ** --------------------------------------------------------------------------*/ // the game's window title name -constexpr const char *GAME_NAME = "Independent Study v0.7 alpha - NOW WITH lights and snow and stuff"; +constexpr const char *GAME_NAME = "Independent Study v0.8 alpha - NOW WITH decent shaders"; // SDL's window object SDL_Window *window = NULL; @@ -90,6 +90,15 @@ GLuint mouseTex; // the center of the screen vec2 offset; +/* + * fps contains the game's current FPS, debugY contains the player's + * y coordinates, updated at a certain interval. These are used in + * the debug menu (see below). + */ + +static unsigned int fps=0; +static float debugY=0; + // handles all logic operations void logic(void); @@ -270,8 +279,20 @@ int main(int argc, char *argv[]){ // the main loop, in all of its gloriousness.. gameRunning = true; std::thread([&]{ - while (gameRunning) + while (gameRunning) { mainLoop(); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + }).detach(); + + // the debug loop, gets debug screen values + std::thread([&]{ + while (gameRunning) { + fps = 1000 / game::time::getDeltaTime(); + debugY = player->loc.y; + + std::this_thread::sleep_for(std::chrono::seconds(1)); + } }).detach(); while (gameRunning) @@ -299,18 +320,7 @@ int main(int argc, char *argv[]){ return 0; // Calls everything passed to atexit } -/* - * fps contains the game's current FPS, debugY contains the player's - * y coordinates, updated at a certain interval. These are used in - * the debug menu (see below). - */ - -static unsigned int fps=0; -static float debugY=0; - void mainLoop(void){ - static unsigned int debugDiv=0; // A divisor used to update the debug menu if it's open - game::time::mainLoopHandler(); if (currentMenu) { @@ -324,16 +334,7 @@ void mainLoop(void){ currentWorld->update(player, game::time::getDeltaTime(), game::time::getTickCount()); currentWorld->detect(player); - - if (++debugDiv == 20) { - debugDiv=0; - - fps = 1000 / game::time::getDeltaTime(); - debugY = player->loc.y; - } } - - SDL_Delay(1); } void render() { @@ -354,10 +355,10 @@ void render() { offset.y = std::max(player->loc.y + player->height / 2, SCREEN_HEIGHT / 2.0f); // "setup" - glm::mat4 projection = glm::ortho( static_cast(floor(offset.x-SCREEN_WIDTH/2)), //left - static_cast(floor(offset.x+SCREEN_WIDTH/2)), //right - static_cast(floor(offset.y-SCREEN_HEIGHT/2)), //bottom - static_cast(floor(offset.y+SCREEN_HEIGHT/2)), //top + glm::mat4 projection = glm::ortho( floor(offset.x-SCREEN_WIDTH/2), //left + floor(offset.x+SCREEN_WIDTH/2), //right + floor(offset.y-SCREEN_HEIGHT/2), //bottom + floor(offset.y+SCREEN_HEIGHT/2), //top 10.0f, //near -10.0f); //far @@ -390,7 +391,7 @@ void render() { * Call the world's draw function, drawing the player, the world, the background, and entities. Also * draw the player's inventory if it exists. */ - player->near = true; // allow player's name to be drawn + //player->near = true; // allow player's name to be drawn currentWorld->draw(player); // draw the player's inventory diff --git a/src/entities.cpp b/src/entities.cpp index 18c91ed..2d9de76 100644 --- a/src/entities.cpp +++ b/src/entities.cpp @@ -941,11 +941,12 @@ Particles::Particles(float x, float y, float w, float h, float vx, float vy, Col bounce = false; index = Texture::getIndex(c); zOffset = ((rand()%20)-10)/1000.0f; + stu = nullptr; } void Particles::draw(GLfloat*& p) const { - vec2 tc = vec2(0.25f * this->index.x, 0.125f * (8.0f - this->index.y)); + vec2 tc = vec2(0.25f * index.x, 0.125f * (8.0f - index.y)); float z = 0.9; if (behind) @@ -1004,6 +1005,8 @@ void Particles::draw(GLfloat*& p) const void Particles::update(float _gravity, float ground_y) { + auto delta = game::time::getDeltaTime(); + // handle ground collision if (loc.y < ground_y) { loc.y = ground_y; @@ -1020,13 +1023,16 @@ void Particles::update(float _gravity, float ground_y) // handle gravity else if (gravity && vel.y > -1.0f) { - vel.y -= _gravity * game::time::getDeltaTime(); + vel.y -= _gravity * delta; } + + // handle lifetime + duration -= delta; } -bool Particles::kill(float delta) +bool Particles::timeUp(void) { - return (duration -= delta) <= 0; + return !(duration > 0); } void Player::save(void) { diff --git a/src/world.cpp b/src/world.cpp index f13c3b7..5ab20ed 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -311,7 +311,7 @@ void World::drawBackgrounds(void) static GLuint starTex = Texture::genColor(Color(255, 255, 255)); - const static float stardim = 2; + constexpr const static float stardim = 2; GLfloat star_coord[star.size() * 5 * 6 + 1]; GLfloat *si = &star_coord[0]; @@ -718,15 +718,15 @@ void World::draw(Player *p) std::vector partVec(pss); GLfloat *pIndex = &partVec[0]; - - for (uint p = 0; p < ps; p++) { + + for (const auto &p : particles) { pc += 30; if (pc > pss) { // TODO resize the vector or something better than breaking - std::cout << "Whoops:" << pc << "," << partVec.size() << std::endl; + //std::cout << "Whoops:" << pc << "," << partVec.size() << std::endl; break; } - particles[p].draw(pIndex); + p.draw(pIndex); } glVertexAttribPointer(worldShader_attribute_coord, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &partVec[0]); @@ -896,6 +896,7 @@ detect(Player *p) 2500 // duration (ms) ); particles.back().fountain = true; + particles.back().stu = b; } break; case FIRE_PIT: @@ -911,6 +912,7 @@ detect(Player *p) ); particles.back().gravity = false; particles.back().behind = true; + particles.back().stu = b; } break; default: @@ -968,25 +970,20 @@ update(Player *p, unsigned int delta, unsigned int ticks) } } // iterate through particles - particles.erase(std::remove_if(particles.begin(), particles.end(), [&delta](Particles &part) { - return part.kill(delta); - }), - particles.end()); - - for (auto part = particles.begin(); part != particles.end(); part++) { - auto pa = *part; - - if (pa.canMove) { - (*part).loc.y += pa.vel.y * delta; - (*part).loc.x += pa.vel.x * delta; - - if (std::any_of(std::begin(build), std::end(build), [pa](const Structures *s) { - return (s->bsubtype == FOUNTAIN) && - (pa.loc.x >= s->loc.x) && (pa.loc.x <= s->loc.x + s->width) && - (pa.loc.y <= s->loc.y + s->height * 0.25f); - })) { - particles.erase(part); - } + particles.remove_if([](const Particles &part) { + return part.duration <= 0; + }); + + for (auto &pa : particles) { + if (pa.canMove) { // causes overhead + pa.loc.y += pa.vel.y * delta; + pa.loc.x += pa.vel.x * delta; + + if (pa.stu != nullptr) { + if (pa.loc.x >= pa.stu->loc.x && pa.loc.x <= pa.stu->loc.x + pa.stu->width && + pa.loc.y <= pa.stu->loc.y + pa.stu->height * 0.25f) + pa.duration = 0; + } } } diff --git a/xml/playerSpawnHill1.xml b/xml/playerSpawnHill1.xml index 13fa3db..6a65fb1 100644 --- a/xml/playerSpawnHill1.xml +++ b/xml/playerSpawnHill1.xml @@ -8,7 +8,7 @@ - + -- cgit v1.2.3 From f4632d58014dce0edc2d447dc934bae9cf957439 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Fri, 3 Jun 2016 08:47:13 -0400 Subject: coolarray, particles are good now --- Changelog | 8 ++++ brice.dat | 4 +- include/coolarray.hpp | 113 +++++++++++++++++++++++++++++++++++++++++++++++ include/entities.hpp | 2 + include/world.hpp | 3 +- src/entities.cpp | 4 +- src/world.cpp | 6 +-- xml/playerSpawnHill1.xml | 20 +++++---- 8 files changed, 143 insertions(+), 17 deletions(-) create mode 100644 include/coolarray.hpp (limited to 'src/entities.cpp') diff --git a/Changelog b/Changelog index 1dd6ef3..ec4a00e 100644 --- a/Changelog +++ b/Changelog @@ -1027,3 +1027,11 @@ - entitys can modify their XMLs - 'alive' XML attribute works - lighting's pretty neat + +6/3/2016: +========= + + - majorly improved particle handling, made CoolArray + - found bugs in quest handling... + - making lights and stars n stuff goood + - story??? art??? music??? diff --git a/brice.dat b/brice.dat index 4bfeac6..bda8adc 100644 --- a/brice.dat +++ b/brice.dat @@ -1,5 +1,5 @@ 2 -canJump -1 canSprint 1 +canJump +1 diff --git a/include/coolarray.hpp b/include/coolarray.hpp new file mode 100644 index 0000000..3e167b7 --- /dev/null +++ b/include/coolarray.hpp @@ -0,0 +1,113 @@ +#ifndef COOLARRAY_H_ +#define COOLARRAY_H_ + +#include +#include + +template +class CoolArray { +private: + T *buffer; + size_t _size, _capacity; +public: + CoolArray(void) { + buffer = nullptr; + _size = 0; + _capacity = 0; + } + + CoolArray(size_t n, const T& value) { + buffer = new T[n]; + _size = n; + _capacity = n; + std::fill(buffer, buffer + _size, value); + } + + ~CoolArray(void) { + delete[] buffer; + } + + T& operator[](size_t idx) { + return buffer[idx]; + } + + void operator=(std::initializer_list a) { + if (buffer != nullptr) + delete[] buffer; + + _size = a.size(); + buffer = new T[_size]; + _capacity = _size; + std::copy(a.begin(), a.end(), buffer); + } + + template + void remove_if(Func f) { + for (size_t i = 0; i < _size; ++i) { + if (f(buffer[i])) + std::move(buffer + i + 1, buffer + _size--, buffer + i); + } + } + + void reserve(size_t n) { + if (buffer != nullptr) { + T *newbuf = new T[n]; + std::copy(buffer, buffer + (_size < n ? _size : n), newbuf); + _capacity = n; + delete[] buffer; + buffer = newbuf; + } else { + buffer = new T[n]; + _capacity = n; + } + } + + void resize(size_t n) { + reserve(n); + _size = n; + } + + void clear(void) { + delete[] buffer; + _size = 0; + _capacity = 0; + } + + size_t size(void) const { + return _size; + } + + size_t capacity(void) const { + return _capacity; + } + + T& front(void) { + return buffer[0]; + } + + T& back(void) { + return buffer[_size - 1]; + } + + T* begin(void) { + return buffer; + } + + T* end(void) { + return buffer + _size; + } + + void push_back(const T& x) { + if (_size >= _capacity) + reserve(_capacity + 5); + + buffer[_size++] = x; + } + + void pop_back(void) { + --_size; + } +}; + + +#endif // COOLARRAY_H_ diff --git a/include/entities.hpp b/include/entities.hpp index 61ecc43..e406397 100644 --- a/include/entities.hpp +++ b/include/entities.hpp @@ -419,6 +419,8 @@ public: Structures *stu; + Particles(void){} + // creates a particle with the desired characteristics Particles(float x, float y, float w, float h, float vx, float vy, Color c, float d); diff --git a/include/world.hpp b/include/world.hpp index 2494120..26811ae 100644 --- a/include/world.hpp +++ b/include/world.hpp @@ -9,6 +9,7 @@ // local game includes #include #include +#include /** * The background type enum. @@ -256,7 +257,7 @@ protected: * * @see addParticle() */ - std::list particles; + CoolArray particles; /** * A vector of all structures in the world. diff --git a/src/entities.cpp b/src/entities.cpp index 2d9de76..f59b462 100644 --- a/src/entities.cpp +++ b/src/entities.cpp @@ -133,10 +133,10 @@ void Entity::die(void) alive = false; health = 0; - if (xmle) { + /*if (xmle) { xmle->SetAttribute("alive", false); currentXMLDoc.SaveFile(currentXML.c_str(), false); - } + }*/ } bool Entity::isAlive(void) const diff --git a/src/world.cpp b/src/world.cpp index 5ab20ed..b096180 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -718,7 +718,7 @@ void World::draw(Player *p) std::vector partVec(pss); GLfloat *pIndex = &partVec[0]; - + for (const auto &p : particles) { pc += 30; if (pc > pss) { @@ -1487,14 +1487,14 @@ addObject(std::string in, std::string p, float x, float y) void World:: addParticle(float x, float y, float w, float h, float vx, float vy, Color color, int d) { - particles.emplace_back(x, y, w, h, vx, vy, color, d); + particles.push_back(Particles(x, y, w, h, vx, vy, color, d)); particles.back().canMove = true; } void World:: addParticle(float x, float y, float w, float h, float vx, float vy, Color color, int d, unsigned char flags) { - particles.emplace_back(x, y, w, h, vx, vy, color, d); + particles.push_back(Particles(x, y, w, h, vx, vy, color, d)); particles.back().canMove = true; particles.back().gravity = flags & (1 << 0); particles.back().bounce = flags & (1 << 1); diff --git a/xml/playerSpawnHill1.xml b/xml/playerSpawnHill1.xml index 6a65fb1..0f19f9a 100644 --- a/xml/playerSpawnHill1.xml +++ b/xml/playerSpawnHill1.xml @@ -5,7 +5,7 @@ - + @@ -38,14 +38,14 @@ And it wasn't stormy. Hello there! My name is Ralph. - 300 + 300 You should go talk to my friend Johnny. He's a pretty chill dude. Niice. - + Go check out Johnny. He's cool. @@ -54,9 +54,9 @@ And it wasn't stormy. Sup bro! Have a quest. To complete it, just go talk to Ralph again. - - Dank MayMay,2 - Wood Sword,1 + + Dank MayMay,2 + Wood Sword,1 @@ -67,8 +67,10 @@ And it wasn't stormy. Hey friend! It's dangerous out there, here take these! - - Wait, promise you'll stop by my stand in the local market! - + + + + + -- cgit v1.2.3