aboutsummaryrefslogtreecommitdiffstats
path: root/src/world.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/world.cpp')
-rw-r--r--src/world.cpp1798
1 files changed, 831 insertions, 967 deletions
diff --git a/src/world.cpp b/src/world.cpp
index b2e1cfb..5ce0b2d 100644
--- a/src/world.cpp
+++ b/src/world.cpp
@@ -1,158 +1,225 @@
+#include <algorithm>
+#include <sstream>
+
#include <world.h>
#include <ui.h>
-#define getWidth(w) ((w->lineCount-GEN_INC)*HLINE) // Calculates the width of world 'w'
+#include <tinyxml2.h>
+using namespace tinyxml2;
-#define GEN_INIT 60
+/**
+ * Defines how many HLINEs tall a blade of grass can be.
+ */
-#define GRASS_HEIGHT 4 // Defines how long the grass layer of a line should be in multiples of HLINE.
+#define GRASS_HEIGHT 4
+/**
+ * Defines the height of the floor in an IndoorWorld.
+ */
-#define DRAW_Y_OFFSET 50 // Defines how many pixels each layer should be offset from each other on the y axis when drawn.
-#define DRAW_SHADE 30 // Defines a shade increment for draw()
+#define INDOOR_FLOOR_HEIGHT 100
-#define INDOOR_FLOOR_HEIGHT 100 // Defines how high the base floor of an IndoorWorld should be
-bool worldInside = false; // True if player is inside a structure
+extern Player *player; // main.cpp?
+extern World *currentWorld; // main.cpp
+extern int commonAIFunc(NPC *); // entities.cpp
+extern void commonTriggerFunc(Mob *); // entities.cpp
+extern bool inBattle;
+
+extern unsigned int tickCount; // main.cpp
+
+int worldShade = 0;
-WEATHER weather = SUNNY;
+std::string currentXML;
+std::vector<std::string> inside; // tracks indoor worlds
+
+std::vector<World *> battleNest; // tracks arenas
+std::vector<vec2> battleNestLoc; // keeps arena locations
+
+/**
+ * Contains the current weather, used in many other places/files.
+ */
+
+WorldWeather weather = WorldWeather::Sunny;
const std::string bgPaths[2][9]={
- {"bg.png", // Daytime background
- "bgn.png", // Nighttime background
- "bgFarMountain.png", // Furthest layer
- "forestTileFar.png", // Furthest away Tree Layer
- "forestTileBack.png", // Closer layer
- "forestTileMid.png", // Near layer
- "forestTileFront.png", // Closest layer
- "dirt.png", // Dirt
- "grass.png"}, // Grass
- {"bgWoodTile.png",
- "bgWoodTile.png",
- "bgWoodTile.png",
- "bgWoodTile.png",
- "bgWoodTile.png",
- "bgWoodTile.png",
- "bgWoodTile.png",
- "bgWoodTile.png"}
+ {"bg.png", // Daytime background
+ "bgn.png", // Nighttime background
+ "bgFarMountain.png", // Furthest layer
+ "forestTileFar.png", // Furthest away Tree Layer
+ "forestTileBack.png", // Closer layer
+ "forestTileMid.png", // Near layer
+ "forestTileFront.png", // Closest layer
+ "dirt.png", // Dirt
+ "grass.png"}, // Grass
+ {"bgWoodTile.png",
+ "bgWoodTile.png",
+ "bgWoodTile.png",
+ "bgWoodTile.png",
+ "bgWoodTile.png",
+ "bgWoodTile.png",
+ "bgWoodTile.png",
+ "bgWoodTile.png"}
};
-const std::string buildPaths[] = { "townhall.png",
- "house1.png",
- "house2.png",
- "house1.png",
- "house1.png",
- "fountain1.png",
- "lampPost1.png",
- "brazzier.png"};
+const std::string buildPaths[] = {
+ "townhall.png",
+ "house1.png",
+ "house2.png",
+ "house1.png",
+ "house1.png",
+ "fountain1.png",
+ "lampPost1.png",
+ "brazzier.png"
+};
+
+/**
+ * Constants used for layer drawing in World::draw(), releated to transparency.
+ */
const float bgDraw[4][3]={
- {100,240,.6 },
- {150,250,.4 },
- {200,255,.25},
- {255,255,.1}
+ { 100, 240, 0.6 },
+ { 150, 250, 0.4 },
+ { 200, 255, 0.25 },
+ { 255, 255, 0.1 }
};
-float worldGetYBase(World *w){
-// World *tmp = w;
- float base = GEN_MIN;
-/* while(tmp->infront){
- tmp = tmp->infront;
- base -= DRAW_Y_OFFSET;
- }*/
- if(!w)return 0;
- return base;
-}
-
-void World::setBackground(WORLD_BG_TYPE bgt){
- bgType = bgt;
- switch(bgt){
- case BG_FOREST:
- bgTex = new Texturec(bgFiles);
+/**
+ * Sets the desired theme for the world's background.
+ *
+ * The images chosen for the background layers are selected depending on the
+ * world's background type.
+ */
+
+void World::
+setBackground( WorldBGType bgt )
+{
+ // load textures with a limit check
+ switch ( (bgType = bgt) ) {
+ case WorldBGType::Forest:
+ bgTex = new Texturec( bgFiles );
break;
- case BG_WOODHOUSE:
- bgTex = new Texturec(bgFilesIndoors);
+
+ case WorldBGType::WoodHouse:
+ bgTex = new Texturec( bgFilesIndoors );
break;
+
+ default:
+ UserError( "Invalid world background type" );
+ break;
}
}
-void World::setStyle(const char* pre){
- std::string prefix = pre ? pre : "assets/style/classic/";
- for(uint i = 0; i < arrAmt(buildPaths);i++){
- sTexLoc.push_back(prefix);
- sTexLoc.back() += buildPaths[i];
- //std::cout << sTexLoc.back() << std::endl;
- }
+/**
+ * Sets the world's style.
+ *
+ * The world's style will determine what sprites are used for things like\
+ * generic structures.
+ */
+
+void World::
+setStyle( std::string pre )
+{
+ unsigned int i;
+
+ // get folder prefix
+ std::string prefix = pre.empty() ? "assets/style/classic/" : pre;
+
+ for ( i = 0; i < arrAmt(buildPaths); i++ )
+ sTexLoc.push_back( prefix + buildPaths[i] );
+
prefix += "bg/";
- for(uint i = 0; i < arrAmt(bgPaths[0]);i++){
- bgFiles.push_back(prefix);
- bgFiles.back() += bgPaths[0][i];
- //std::cout << bgFiles.back() << std::endl;
- }
- for(uint i = 0; i < arrAmt(bgPaths[1]);i++){
- bgFilesIndoors.push_back(prefix);
- bgFilesIndoors.back() += bgPaths[1][i];
- //std::cout << bgFilesIndoors.back() << std::endl;
- }
+
+ for ( i = 0; i < arrAmt(bgPaths[0]); i++ )
+ bgFiles.push_back( prefix + bgPaths[0][i] );
+
+ for ( i = 0; i < arrAmt(bgPaths[1]); i++ )
+ bgFilesIndoors.push_back( prefix + bgPaths[1][i] );
}
-World::World(void){
-
- bgm = NULL;
- bgmObj = NULL;
-
- toLeft =
- toRight = NULL;
-
- /*
- * Allocate and clear an array for star coordinates.
- */
-
- star = new vec2[100];
- memset(star,0,100 * sizeof(vec2));
+/**
+ * Creates a world object.
+ *
+ * Note that all this does is nullify pointers, to prevent as much disaster as
+ * possible. Functions like setBGM(), setStyle() and generate() should be called
+ * before the World is actually put into use.
+ */
+
+World::
+World( void )
+{
+ bgmObj = NULL;
+
+ toLeft = NULL;
+ toRight = NULL;
}
-void World::deleteEntities(void){
- while(!mob.empty()){
+/**
+ * The entity vector destroyer.
+ *
+ * This function will free all memory used by all entities, and then empty the
+ * vectors they were stored in.
+ */
+
+void World::
+deleteEntities( void )
+{
+ // free mobs
+ while ( !mob.empty() ) {
delete mob.back();
mob.pop_back();
}
+
+ merchant.clear();
while(!npc.empty()){
delete npc.back();
npc.pop_back();
}
- while(!build.empty()){
+
+ // free structures
+ while ( !build.empty() ) {
delete build.back();
build.pop_back();
}
- while(!object.empty()){
+
+ // free objects
+ while ( !object.empty() ) {
delete object.back();
object.pop_back();
}
- while(!entity.empty()){
- entity.pop_back();
- }
- while(!particles.empty()){
- delete particles.back();
- particles.pop_back();
- }
- while(!light.empty()){
- light.pop_back();
+
+ // clear entity array
+ entity.clear();
+
+ // free particles
+ particles.clear();
+
+ // clear light array
+ light.clear();
+
+ // free villages
+ while ( !village.empty() ) {
+ delete village.back();
+ village.pop_back();
}
}
-World::~World(void){
- /*if(behind != NULL)
- delete behind;*/
-
+/**
+ * The world destructor.
+ *
+ * This will free objects used by the world itself, then free the vectors of
+ * entity-related objects.
+ */
+
+World::
+~World( void )
+{
+ // sdl2_mixer's object
if(bgmObj)
Mix_FreeMusic(bgmObj);
- if(bgm)
- delete[] bgm;
+
delete bgTex;
- delete[] star;
- delete[] line;
delete[] toLeft;
delete[] toRight;
@@ -160,634 +227,464 @@ World::~World(void){
deleteEntities();
}
-void World::generate(unsigned int width){ // Generates the world and sets all variables contained in the World class.
- unsigned int i;
- float inc;
-
- /*
- * Calculate the world's real width. The current form of generation fails to generate
- * the last GEN_INC lines, so we offset those making the real real width what was passed
- * to this function.
- *
- * Abort if the width is invalid.
- *
- */
-
- if(width <= 0)
- abort();
+/**
+ * Generates a world of the specified width.
+ *
+ * This will mainly populate the WorldData array, mostly preparing the World
+ * object for usage.
+ */
+
+void World::
+generate( unsigned int width )
+{
+ // iterator for `for` loops
+ std::vector<WorldData>::iterator wditer;
+
+ // see below for description
+ float geninc = 0;
+
+ // check for valid width
+ if ( (int)width <= 0 )
+ UserError("Invalid world dimensions");
+
+ // allocate space for world
+ worldData = std::vector<WorldData> (width + GROUND_HILLINESS, WorldData { false, {0,0}, 0, 0 });
+ lineCount = worldData.size();
+
+ // prepare for generation
+ worldData.front().groundHeight = GROUND_HEIGHT_INITIAL;
+ wditer = worldData.begin();
+
+ // give every GROUND_HILLINESSth entry a groundHeight value
+ for(unsigned int i = GROUND_HILLINESS; i < worldData.size(); i += GROUND_HILLINESS, wditer += GROUND_HILLINESS)
+ worldData[i].groundHeight = (*wditer).groundHeight + (randGet() % 8 - 4);
+
+ // create slopes from the points that were just defined, populate the rest of the WorldData structure
+
+ for(wditer = worldData.begin(); wditer != worldData.end(); wditer++){
+ if ((*wditer).groundHeight)
+ // 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;
+
+ (*wditer).groundColor = randGet() % 32 / 8;
+ (*wditer).grassUnpressed = true;
+ (*wditer).grassHeight[0] = (randGet() % 16) / 3 + 2;
+ (*wditer).grassHeight[1] = (randGet() % 16) / 3 + 2;
+
+ // bound checks
+ if ( (*wditer).groundHeight < GROUND_HEIGHT_MINIMUM )
+ (*wditer).groundHeight = GROUND_HEIGHT_MINIMUM;
+ else if ( (*wditer).groundHeight > GROUND_HEIGHT_MAXIMUM )
+ (*wditer).groundHeight = GROUND_HEIGHT_MAXIMUM;
- lineCount = (width + GEN_INC) / HLINE;
-
- /*
- * Allocate enough memory for the world to be stored.
- */
-
- line = new struct line_t[lineCount];
- memset(line,0,lineCount * sizeof(struct line_t));
-
- /*
- * Set an initial y to base generation off of, as generation references previous lines.
- */
-
- line[0].y = GEN_INIT;
-
- /*
- * Populate every GEN_INCth line structure. The remaining lines will be based off of these.
- */
-
- for(i = GEN_INC;i < lineCount;i += GEN_INC){
-
- /*
- * Generate a y value, ensuring it stays within a reasonable range.
- */
-
- line[i].y = rand() % 8 - 4 + line[i - GEN_INC].y; // Add +/- 4 to the previous line
-
- if(line[i].y < GEN_MIN)line[i].y = GEN_MIN; // Minimum bound
- else if(line[i].y > GEN_MAX)line[i].y = GEN_MAX; // Maximum bound
-
- }
-
- /*
- * Generate values for the remaining lines here.
- */
-
- for(i = 0;i < lineCount - GEN_INC;i++){
-
- /*
- * Every GEN_INCth line calculate the slope between the current line and the one
- * GEN_INC lines before it. This value is then divided into an increment that is
- * added to lines between these two points resulting in a smooth slope.
- *
- */
-
- if(!(i % GEN_INC))
-
- inc = (line[i + GEN_INC].y - line[i].y) / (float)GEN_INC;
-
- /*
- * Add the increment to create the smooth slope.
- */
-
- else line[i].y = line[i - 1].y + inc;
-
- /*
- * Generate a color value for the line. This will be referenced in World->draw(),
- * by setting an RGB value of color (red), color - 50 (green), color - 100 (blue).
- */
-
- line[i].color = rand() % 32 / 8; // 100 to 120
+ if( (*wditer).groundHeight <= 0 )
+ (*wditer).groundHeight = GROUND_HEIGHT_MINIMUM;
- /*
- * Each line has two 'blades' of grass, here we generate random heights for them.
- */
-
- line[i].gh[0] = (getRand() % 16) / 3.5 + 2; // Not sure what the range resolves to here...
- line[i].gh[1] = (getRand() % 16) / 3.5 + 2; //
-
- line[i].gs = true; // Show the blades of grass (modified by the player)
-
- }
-
- /*
- * Calculate the x coordinate to start drawing this world from so that it is centered at (0,0).
- */
-
- x_start = 0 - getWidth(this) / 2;
+ }
+
+ // define x-coordinate of world's leftmost 'line'
+ worldStart = (width - GROUND_HILLINESS) * HLINE / 2 * -1;
- /*
- * Assign coordinates for the stars, seen at nighttime.
- */
-
- for(i = 0;i < 100;i++){
- star[i].x = getRand() % getTheWidth() - getTheWidth() / 2;
- star[i].y = getRand() % SCREEN_HEIGHT + 100;
+ // create empty star array, should be filled here as well...
+ star = std::vector<vec2> (100, vec2 { 0, 400 } );
+ for ( auto &s : star ) {
+ s.x = (getRand() % (-worldStart * 2)) + worldStart;
+ s.y = (getRand() % SCREEN_HEIGHT) + 100.0f;
}
}
-void World::generateFunc(unsigned int width,float(*func)(float)){
- unsigned int i;
-
- /*
- * Check for a valid width.
- */
-
- if((lineCount = width) <= 0)
- abort();
-
- /*
- * Allocate memory for the line array.
- */
-
- line = new struct line_t[lineCount];
- memset(line,0,lineCount*sizeof(struct line_t));
-
- /*
- * Populate entries in the line array, using `func` to get y values.
- */
-
- for(i = 0;i < lineCount;i++){
- line[i].y = func(i);
-
- if(line[i].y < 0)line[i].y = 0; // Minimum bound
- if(line[i].y > 2000)line[i].y = 2000; // Maximum bound
-
- line[i].color = rand() % 20 + 100;
-
- line[i].gh[0] = (getRand() % 16) / 3.5 + 2;
- line[i].gh[1] = (getRand() % 16) / 3.5 + 2;
-
- line[i].gs = true;
- }
-
- x_start = 0 - getWidth(this) / 2;
-
- for(i = 0;i < 100;i++){
- star[i].x = getRand() % getTheWidth() - getTheWidth() / 2;
- star[i].y = getRand() % SCREEN_HEIGHT + 100;
- }
-}
+/**
+ * Updates all entity and player coordinates with their velocities.
+ *
+ * Also handles music fading, although that could probably be placed elsewhere.
+ */
-void World::update(Player *p,unsigned int delta){
-
- /*
- * Update the player's coordinates.
- */
-
+void World::
+update( Player *p, unsigned int delta )
+{
+ // update player coords
p->loc.y += p->vel.y * delta;
p->loc.x +=(p->vel.x * p->speed) * delta;
- /*
- * Update coordinates of all entities except for structures.
- */
-
- for(auto &e : entity){
+ // update entity coords
+ for ( auto &e : entity ) {
e->loc.y += e->vel.y * delta;
- if(e->type != STRUCTURET && e->canMove){
+ // dont let structures move?
+ if ( e->type != STRUCTURET && e->canMove ) {
e->loc.x += e->vel.x * delta;
- if(e->vel.x < 0)e->left = true;
- else if(e->vel.x > 0)e->left = false;
+ // update boolean directions
+ if ( e->vel.x < 0 )
+ e->left = true;
+ else if ( e->vel.x > 0 )
+ e->left = false;
}
}
+ // 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++ ) {
+ if ( (*part).canMove ) {
+ (*part).loc.y += (*part).vely * delta;
+ (*part).loc.x += (*part).velx * delta;
+
+ for ( auto &b : build ) {
+ if ( b->bsubtype == FOUNTAIN ) {
+ if ( (*part).loc.x >= b->loc.x && (*part).loc.x <= b->loc.x + b->width ) {
+ if ( (*part).loc.y <= b->loc.y + b->height * .25)
+ particles.erase( part );
- for(unsigned int i=0;i<particles.size();i++){
- if(particles[i]->kill(delta)){
- delete particles[i];
- particles.erase(particles.begin()+i);
- }else if(particles[i]->canMove){
- particles[i]->loc.y += particles[i]->vely * delta;
- particles[i]->loc.x += particles[i]->velx * delta;
-
- for(auto &b : build){
- if(b->bsubtype==FOUNTAIN){
- if(particles[i]->loc.x >= b->loc.x && particles[i]->loc.x <= b->loc.x + b->width){
- if(particles[i]->loc.y <= b->loc.y + b->height * .25){
- delete particles[i];
- particles.erase(particles.begin()+i);
- }
}
}
}
}
}
- if(ui::dialogImportant){
+ // handle music fades
+ if ( ui::dialogImportant )
Mix_FadeOutMusic(2000);
- }else if(!Mix_PlayingMusic()){
+ else if( !Mix_PlayingMusic() )
Mix_FadeInMusic(bgmObj,-1,2000);
- }
}
-void World::setBGM(std::string path){
- bgm = new char[path.size() + 1];
- strcpy(bgm,path.c_str());
- bgmObj = Mix_LoadMUS(bgm);
+/**
+ * Set the world's BGM.
+ *
+ * This will load a sound file to be played while the player is in this world.
+ * If no file is found, no music should play.
+ */
+
+void World::
+setBGM( std::string path )
+{
+ if( !path.empty() )
+ bgmObj = Mix_LoadMUS( (bgm = path).c_str() );
}
-void World::bgmPlay(World *prev){
- if(prev){
- if(bgm != prev->bgm){
- Mix_FadeOutMusic(800);
- //Mix_VolumeMusic(50);
- Mix_PlayMusic(bgmObj,-1); // Loop infinitely
+/**
+ * Toggle play/stop of the background music.
+ *
+ * If new music is to be played a crossfade will occur, otherwise... uhm.
+ */
+
+void World::
+bgmPlay( World *prev ) const
+{
+ if ( prev ) {
+ if ( bgm != prev->bgm ) {
+ // new world, new music
+ Mix_FadeOutMusic( 800 );
+ Mix_PlayMusic( bgmObj, -1 );
}
- }else{
- Mix_FadeOutMusic(800);
- //Mix_VolumeMusic(50);
- Mix_PlayMusic(bgmObj,-1); // Loop infinitely
+ } else {
+ // first call
+ Mix_FadeOutMusic( 800 );
+ Mix_PlayMusic( bgmObj, -1 );
}
}
-int worldShade = 0;
-
-extern vec2 offset;
-extern unsigned int tickCount;
-
-void World::draw(Player *p){
- static float yoff=DRAW_Y_OFFSET; // Initialize stuff
- static int shade,bgshade;
- static World *current=this;
- unsigned int i;
- int is,ie,v_offset,cx_start,width;
- struct line_t *cline;
- float base;
-
- bgshade = worldShade << 1; // *2
- base = worldGetYBase(this);
+/**
+ * The world draw function.
+ *
+ * This function will draw the background layers, entities, and player to the
+ * screen.
+ */
+
+void World::
+draw( Player *p )
+{
+ // iterators
+ int i, iStart, iEnd;
+
+ // shade value for draws -- may be unnecessary
+ int shadeBackground = -worldShade;
+
+ // player's offset in worldData[]
+ int pOffset;
+
+ // world width in pixels
+ int width = worldData.size() * HLINE;
+
+ // shade value for GLSL
+ float shadeAmbient = -worldShade / 50.0f + 0.5f; // -0.5f to 1.5f
+ if ( shadeAmbient < 0 )
+ shadeAmbient = 0;
+ else if ( shadeAmbient > 0.9f )
+ shadeAmbient = 1;
/*
- * Draw the background images in the appropriate order.
- */
+ * Draw background images.
+ */
-//LLLOOP:
- /*if(current->infront){
- current=current->infront;
- goto LLLOOP;
- }*/
+ glEnable( GL_TEXTURE_2D );
- if(current->x_start < SCREEN_WIDTH * -.5 )
- cx_start = current->x_start * 1.5;
- else
- cx_start = (int)(SCREEN_WIDTH * -.5);
-
- width = (-cx_start) << 1;
+ // the sunny wallpaper is faded with the night depending on tickCount
- glEnable(GL_TEXTURE_2D);
-
- bgTex->bind(0);
- safeSetColorA(255,255,255,255 - worldShade * 4);
- glBegin(GL_QUADS);
- glTexCoord2i(0,0);glVertex2i( cx_start,SCREEN_HEIGHT);
- glTexCoord2i(1,0);glVertex2i(-cx_start,SCREEN_HEIGHT);
- glTexCoord2i(1,1);glVertex2i(-cx_start,0);
- glTexCoord2i(0,1);glVertex2i( cx_start,0);
+ bgTex->bind( 0 );
+ safeSetColorA( 255, 255, 255, 255 - worldShade * 4 );
+
+ glBegin( GL_QUADS );
+ glTexCoord2i( 0, 0 ); glVertex2i( worldStart, SCREEN_HEIGHT );
+ glTexCoord2i( 1, 0 ); glVertex2i( -worldStart, SCREEN_HEIGHT );
+ glTexCoord2i( 1, 1 ); glVertex2i( -worldStart, 0 );
+ glTexCoord2i( 0, 1 ); glVertex2i( worldStart, 0 );
glEnd();
bgTex->bindNext();
- safeSetColorA(255,255,255,worldShade * 4);
- glBegin(GL_QUADS);
- glTexCoord2i(0,0);glVertex2i( cx_start,SCREEN_HEIGHT);
- glTexCoord2i(1,0);glVertex2i(-cx_start,SCREEN_HEIGHT);
- glTexCoord2i(1,1);glVertex2i(-cx_start,0);
- glTexCoord2i(0,1);glVertex2i( cx_start,0);
+ safeSetColorA( 255, 255, 255, worldShade * 4 );
+
+ glBegin( GL_QUADS );
+ glTexCoord2i( 0, 0 ); glVertex2i( worldStart, SCREEN_HEIGHT );
+ glTexCoord2i( 1, 0 ); glVertex2i( -worldStart, SCREEN_HEIGHT );
+ glTexCoord2i( 1, 1 ); glVertex2i( -worldStart, 0 );
+ glTexCoord2i( 0, 1 ); glVertex2i( worldStart, 0 );
glEnd();
- glDisable(GL_TEXTURE_2D);
-
- /*
- * Draws stars if it is an appropriate time of day for them.
- */
+
+ glDisable( GL_TEXTURE_2D );
+
+ // draw the stars if the time deems it appropriate
+
+ //if (((( weather == WorldWeather::Dark ) & ( tickCount % DAY_CYCLE )) < DAY_CYCLE / 2) ||
+ // ((( weather == WorldWeather::Sunny ) & ( tickCount % DAY_CYCLE )) > DAY_CYCLE * .75) ){
+ if ( worldShade > 0 ) {
- if((((weather==DARK )&(tickCount%DAY_CYCLE))<DAY_CYCLE/2) ||
- (((weather==SUNNY)&(tickCount%DAY_CYCLE))>DAY_CYCLE*.75) ){
-
- if(tickCount % DAY_CYCLE){ // The above if statement doesn't check for exact midnight.
-
- safeSetColorA(255,255,255,bgshade + getRand() % 30 - 15);
- for(i = 0; i < 100; i++){
- glRectf(star[i].x+offset.x*.9,
- star[i].y,
- star[i].x+offset.x*.9+HLINE,
- star[i].y+HLINE
- );
- }
-
+ safeSetColorA( 255, 255, 255, 255 - (getRand() % 30 - 15) );
+
+ for ( i = 0; i < 100; i++ ) {
+ glRectf(star[i].x + offset.x * .9,
+ star[i].y,
+ star[i].x + offset.x * .9 + HLINE,
+ star[i].y + HLINE
+ );
}
- }
-
+ }
- glEnable(GL_TEXTURE_2D);
-
- /*
- * Draw the mountains.
- */
- bgTex->bindNext();
- safeSetColorA(150-bgshade,150-bgshade,150-bgshade,220);
+ // draw remaining background items
- glBegin(GL_QUADS);
- for(int i = 0; i <= width/1920; i++){
- glTexCoord2i(0,1);glVertex2i(width/-2+(1920*i )+offset.x*.85,base);
- glTexCoord2i(1,1);glVertex2i(width/-2+(1920*(i+1))+offset.x*.85,base);
- glTexCoord2i(1,0);glVertex2i(width/-2+(1920*(i+1))+offset.x*.85,base+1080);
- glTexCoord2i(0,0);glVertex2i(width/-2+(1920*i )+offset.x*.85,base+1080);
+ glEnable( GL_TEXTURE_2D );
+
+ bgTex->bindNext();
+ safeSetColorA( 150 + shadeBackground * 2, 150 + shadeBackground * 2, 150 + shadeBackground * 2, 255 );
+
+ glBegin( GL_QUADS );
+ for ( i = 0; i <= (int)(worldData.size() * HLINE / 1920); i++ ) {
+ glTexCoord2i( 0, 1 ); glVertex2i( width / 2 * -1 + (1920 * i ) + offset.x * .85, GROUND_HEIGHT_MINIMUM );
+ glTexCoord2i( 1, 1 ); glVertex2i( width / 2 * -1 + (1920 * (i + 1)) + offset.x * .85, GROUND_HEIGHT_MINIMUM );
+ glTexCoord2i( 1, 0 ); glVertex2i( width / 2 * -1 + (1920 * (i + 1)) + offset.x * .85, GROUND_HEIGHT_MINIMUM + 1080 );
+ glTexCoord2i( 0, 0 ); glVertex2i( width / 2 * -1 + (1920 * i ) + offset.x * .85, GROUND_HEIGHT_MINIMUM + 1080 );
}
glEnd();
- /*
- * Draw four layers of trees.
- */
-
- for(i = 0; i < 4; i++){
+ for ( i = 0; i < 4; i++ ) {
bgTex->bindNext();
- safeSetColorA(bgDraw[i][0]-bgshade,bgDraw[i][0]-bgshade,bgDraw[i][0]-bgshade,bgDraw[i][1]);
-
- glBegin(GL_QUADS);
- for(int j = cx_start; j <= -cx_start; j += 600){
- glTexCoord2i(0,1);glVertex2i( j +offset.x*bgDraw[i][2],base);
- glTexCoord2i(1,1);glVertex2i((j+600)+offset.x*bgDraw[i][2],base);
- glTexCoord2i(1,0);glVertex2i((j+600)+offset.x*bgDraw[i][2],base+400);
- glTexCoord2i(0,0);glVertex2i( j +offset.x*bgDraw[i][2],base+400);
+ safeSetColorA( bgDraw[i][0] + shadeBackground * 2, bgDraw[i][0] + shadeBackground * 2, bgDraw[i][0] + shadeBackground * 2, bgDraw[i][1] );
+
+ glBegin( GL_QUADS );
+ for( int j = worldStart; j <= -worldStart; j += 600 ){
+ glTexCoord2i( 0, 1 ); glVertex2i( j + offset.x * bgDraw[i][2], GROUND_HEIGHT_MINIMUM );
+ glTexCoord2i( 1, 1 ); glVertex2i( (j + 600) + offset.x * bgDraw[i][2], GROUND_HEIGHT_MINIMUM );
+ glTexCoord2i( 1, 0 ); glVertex2i( (j + 600) + offset.x * bgDraw[i][2], GROUND_HEIGHT_MINIMUM + 400 );
+ glTexCoord2i( 0, 0 ); glVertex2i( j + offset.x * bgDraw[i][2], GROUND_HEIGHT_MINIMUM + 400 );
}
glEnd();
}
- glDisable(GL_TEXTURE_2D);
+ glDisable( GL_TEXTURE_2D );
- glColor3ub(0,0,0);
- glRectf(cx_start,GEN_MIN,-cx_start,0);
+ // draw black under backgrounds
- /*
- * World drawing is done recursively, meaning that this function jumps
- * back as many 'layers' as it can and then draws, eventually coming
- * back to the initial or 'root' layer. LOOP1 does the recursion back
- * to the furthest behind layer, modifying shade and y offsets as it
- * does.
- *
- */
+ glColor3ub( 0, 0, 0 );
+ glRectf( worldStart, GROUND_HEIGHT_MINIMUM, -worldStart, 0 );
- current=this;
- shade=worldShade;
+ pOffset = (offset.x + p->width / 2 - worldStart) / HLINE;
-//LOOP1:
+ /*
+ * Prepare for world ground drawing.
+ */
+
+ // only draw world within player vision
+
+ if ((iStart = pOffset - (SCREEN_WIDTH / 2 / HLINE) - GROUND_HILLINESS) < 0)
+ iStart = 0;
- //if(current->behind){
-
- /*
- * Add to the y offset and shade values (explained further below)
- * and recurse.
- *
- */
-
- /*yoff+=DRAW_Y_OFFSET;
- shade+=DRAW_SHADE;
- current=current->behind;
- goto LOOP1;
- }*/
-
- /*
- * Here is where the actual world drawing begins. A goto is made to
- * LOOP2 once the current layer is drawn and the function shifts to
- * draw the next closest layer.
- */
-
-//LOOP2:
+ if ((iEnd = pOffset + (SCREEN_WIDTH / 2 / HLINE) + GROUND_HILLINESS + HLINE) > (int)worldData.size())
+ iEnd = worldData.size();
+ else if (iEnd < GROUND_HILLINESS)
+ iEnd = GROUND_HILLINESS;
- /*
- * Calculate the offset in the line array that the player is (or would)
- * currently be on. This function then calculates reasonable values for
- * the 'for' loop below that draws the layer.
- */
+ // draw particles and buildings
- v_offset=(offset.x + p->width / 2 - current->x_start) / HLINE;
-
- // is -> i start
+ std::for_each( particles.begin(), particles.end(), [](Particles part) { if ( part.behind ) part.draw(); });
- is=v_offset - (SCREEN_WIDTH / 2 / HLINE) - GEN_INC;
- if(is<0)is=0; // Minimum bound
+ for ( auto &b : build )
+ b->draw();
+
+ // draw light elements?
- // ie -> i end
+ glEnable( GL_TEXTURE_2D );
+
+ glActiveTexture( GL_TEXTURE0 );
+ bgTex->bindNext();
- ie=v_offset + (SCREEN_WIDTH / 2 / HLINE) + GEN_INC + HLINE;
- if(ie>(int)current->lineCount)ie=current->lineCount; // Maximum bound
- else if(ie < GEN_INC)ie = GEN_INC;
+ std::unique_ptr<GLfloat[]> pointArrayBuf = std::make_unique<GLfloat[]> (2 * (light.size() + p->light));
+ auto pointArray = pointArrayBuf.get();
- /*
- * Make more direct variables for quicker referencing.
- */
+ for ( i = 0; i < (int)light.size(); i++ ) {
+ pointArray[2 * i ] = light[i].loc.x - offset.x;
+ pointArray[2 * i + 1] = light[i].loc.y;
+ }
- cline =current->line;
- cx_start=current->x_start;
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
- /*
- * Invert shading if desired.
- */
+ glUseProgram( shaderProgram );
+ glUniform1i( glGetUniformLocation( shaderProgram, "sampler"), 0 );
+ glUniform1f( glGetUniformLocation( shaderProgram, "amb" ), shadeAmbient );
- shade*=-1;
+ if ( p->light ) {
+ pointArray[2 * (light.size() + 1) ] = (float)( p->loc.x + SCREEN_WIDTH / 2 );
+ pointArray[2 * (light.size() + 1) + 1] = (float)( p->loc.y );
+ }
- /*
- * Draw structures. We draw structures behind the dirt/grass so that the building's
- * corners don't stick out.
- */
-
- for(auto &part : particles){
- if(part->behind)
- part->draw();
+ if ( light.size() + (int)p->light == 0)
+ glUniform1i( glGetUniformLocation( shaderProgram, "numLight"), 0);
+ else {
+ glUniform1i ( glGetUniformLocation( shaderProgram, "numLight" ), light.size() + (int)p->light );
+ glUniform2fv( glGetUniformLocation( shaderProgram, "lightLocation"), light.size() + (int)p->light, pointArray );
+ glUniform3f ( glGetUniformLocation( shaderProgram, "lightColor" ), 1.0f, 1.0f, 1.0f );
}
- for(auto &b : current->build){
- b->draw();
- }
- /*
- * Draw the layer up until the grass portion, which is done later.
- */
-
- bool hey=false;
- glEnable(GL_TEXTURE_2D);
- glActiveTexture(GL_TEXTURE0);
- bgTex->bindNext();
+
+ /*
+ * Draw the dirt.
+ */
+
+ glBegin( GL_QUADS );
+
+ // faulty
+ /*glTexCoord2i(0 ,0);glVertex2i(pOffset - (SCREEN_WIDTH / 1.5),0);
+ glTexCoord2i(64,0);glVertex2i(pOffset + (SCREEN_WIDTH / 1.5),0);
+ glTexCoord2i(64,1);glVertex2i(pOffset + (SCREEN_WIDTH / 1.5),GROUND_HEIGHT_MINIMUM);
+ glTexCoord2i(0 ,1);glVertex2i(pOffset - (SCREEN_WIDTH / 1.5),GROUND_HEIGHT_MINIMUM);*/
- GLfloat pointArray[light.size() + (int)p->light][2];
- for(uint w = 0; w < light.size(); w++){
- pointArray[w][0] = light[w].loc.x - offset.x;
- pointArray[w][1] = light[w].loc.y;
- }
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); //for the s direction
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); //for the t direction
- glUseProgram(shaderProgram);
- glUniform1i(glGetUniformLocation(shaderProgram, "sampler"), 0);
- glUniform1f(glGetUniformLocation(shaderProgram, "amb"), float(shade+50.0f)/100.0f);
- if(p->light){
- //glUniform1i(glGetUniformLocation(shaderProgram, "numLight"), 1);
- //glUniform2f(glGetUniformLocation(shaderProgram, "lightLocation"), p->loc.x - offset.x+SCREEN_WIDTH/2, p->loc.y);
- //glUniform3f(glGetUniformLocation(shaderProgram, "lightColor"), 1.0f,1.0f,1.0f);
- pointArray[light.size()+1][0] = (float)(p->loc.x + SCREEN_WIDTH/2);
- pointArray[light.size()+1][1] = (float)(p->loc.y);
- }
- if(light.size()+(int)p->light == 0){
- glUniform1i(glGetUniformLocation(shaderProgram, "numLight"), 0);
- }else{
- glUniform1i (glGetUniformLocation(shaderProgram, "numLight"), light.size()+(int)p->light);
- glUniform2fv(glGetUniformLocation(shaderProgram, "lightLocation"), light.size()+(int)p->light, (GLfloat *)&pointArray);
- glUniform3f (glGetUniformLocation(shaderProgram, "lightColor"), 1.0f,1.0f,1.0f);
- }
+ for ( i = iStart; i < iEnd; i++ ) {
+ if ( worldData[i].groundHeight <= 0 ) {
+ worldData[i].groundHeight = GROUND_HEIGHT_MINIMUM - 1;
+ glColor4ub( 0, 0, 0, 255 );
+ } else
+ safeSetColorA( 150, 150, 150, 255 );
- glBegin(GL_QUADS);
+ 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, (int)(worldData[i].groundHeight / 64) + worldData[i].groundColor ); glVertex2i(worldStart + i * HLINE + HLINE, 0 );
+ glTexCoord2i( 0, (int)(worldData[i].groundHeight / 64) + worldData[i].groundColor ); glVertex2i(worldStart + i * HLINE , 0 );
+
+ if ( worldData[i].groundHeight == GROUND_HEIGHT_MINIMUM - 1 )
+ worldData[i].groundHeight = 0;
+ }
- glTexCoord2i(0 ,0);glVertex2i(v_offset - (SCREEN_WIDTH / 1.5),0);
- glTexCoord2i(64,0);glVertex2i(v_offset + (SCREEN_WIDTH / 1.5),0);
- glTexCoord2i(64,1);glVertex2i(v_offset + (SCREEN_WIDTH / 1.5),base);
- glTexCoord2i(0 ,1);glVertex2i(v_offset - (SCREEN_WIDTH / 1.5),base);
-
- for(i=is;i<(unsigned)ie-GEN_INC;i++){
- cline[i].y+=(yoff-DRAW_Y_OFFSET); // Add the y offset
- if(!cline[i].y){
- cline[i].y=base;
- hey=true;
- glColor4ub(0,0,0,255);
- }else safeSetColorA(150+shade*2,150+shade*2,150+shade*2,255);
- glTexCoord2i(0,0); glVertex2i(cx_start+i*HLINE ,cline[i].y-GRASS_HEIGHT);
- glTexCoord2i(1,0); glVertex2i(cx_start+i*HLINE+HLINE,cline[i].y-GRASS_HEIGHT);
- glTexCoord2i(1,(int)(cline[i].y/64)+cline[i].color);glVertex2i(cx_start+i*HLINE+HLINE,0);
- glTexCoord2i(0,(int)(cline[i].y/64)+cline[i].color);glVertex2i(cx_start+i*HLINE ,0);
- cline[i].y-=(yoff-DRAW_Y_OFFSET); // Restore the line's y value
- if(hey){
- hey=false;
- cline[i].y=0;
- }
- }
glEnd();
+
glUseProgram(0);
glDisable(GL_TEXTURE_2D);
- /*
- * Draw grass on every line.
- */
- float cgh[2];
+ /*
+ * Draw the grass/the top of the ground.
+ */
- glEnable(GL_TEXTURE_2D);
- glActiveTexture(GL_TEXTURE0);
+ glEnable( GL_TEXTURE_2D );
+
+ glActiveTexture( GL_TEXTURE0 );
bgTex->bindNext();
- glUseProgram(shaderProgram);
- glUniform1i(glGetUniformLocation(shaderProgram, "sampler"), 0);
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); //for the s direction
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); //for the t direction
- //glBegin(GL_QUADS);
+
+ glUseProgram( shaderProgram );
+ glUniform1i( glGetUniformLocation( shaderProgram, "sampler"), 0);
- for(i=is;i<(unsigned)ie-GEN_INC;i++){
-
- /*
- * Load the current line's grass values
- */
-
- if(cline[i].y)memcpy(cgh,cline[i].gh,2*sizeof(float));
- else memset(cgh,0 ,2*sizeof(float));
-
-
-
- /*
- * Flatten the grass if the player is standing on it.
- */
+ float cgh[2];
+ for ( i = iStart; i < iEnd - GROUND_HILLINESS; i++ ) {
- if(!cline[i].gs){
- cgh[0]/=4;
- cgh[1]/=4;
+ // load the current line's grass values
+ if ( worldData[i].groundHeight )
+ memcpy( cgh, worldData[i].grassHeight, 2 * sizeof( float ));
+ else
+ memset( cgh, 0 , 2 * sizeof( float ));
+
+ // flatten the grass if the player is standing on it.
+ if( !worldData[i].grassUnpressed ){
+ cgh[0] /= 4;
+ cgh[1] /= 4;
}
- /*
- * Actually draw the grass.
- */
+ // actually draw the grass.
- cline[i].y+=(yoff-DRAW_Y_OFFSET);
- safeSetColorA(255,255,255,255);
- glBegin(GL_QUADS);
- glTexCoord2i(0,0);glVertex2i(cx_start+i*HLINE ,cline[i].y+cgh[0]);
- glTexCoord2i(1,0);glVertex2i(cx_start+i*HLINE+HLINE/2,cline[i].y+cgh[0]);
- glTexCoord2i(1,1);glVertex2i(cx_start+i*HLINE+HLINE/2,cline[i].y-GRASS_HEIGHT);
- glTexCoord2i(0,1);glVertex2i(cx_start+i*HLINE ,cline[i].y-GRASS_HEIGHT);
- glEnd();
-
- glBegin(GL_QUADS);
- glTexCoord2i(0,0);glVertex2i(cx_start+i*HLINE+HLINE/2,cline[i].y+cgh[1]);
- glTexCoord2i(1,0);glVertex2i(cx_start+i*HLINE+HLINE ,cline[i].y+cgh[1]);
- glTexCoord2i(1,1);glVertex2i(cx_start+i*HLINE+HLINE ,cline[i].y-GRASS_HEIGHT);
- glTexCoord2i(0,1);glVertex2i(cx_start+i*HLINE+HLINE/2,cline[i].y-GRASS_HEIGHT);
+ safeSetColorA( 255, 255, 255, 255 );
+
+ glBegin( GL_QUADS );
+ glTexCoord2i( 0, 0 ); glVertex2i( worldStart + i * HLINE , worldData[i].groundHeight + cgh[0] );
+ glTexCoord2i( 1, 0 ); glVertex2i( worldStart + i * HLINE + HLINE / 2, worldData[i].groundHeight + cgh[0] );
+ glTexCoord2i( 1, 1 ); glVertex2i( worldStart + i * HLINE + HLINE / 2, worldData[i].groundHeight - GRASS_HEIGHT );
+ glTexCoord2i( 0, 1 ); glVertex2i( worldStart + i * HLINE , worldData[i].groundHeight - GRASS_HEIGHT );
+ glTexCoord2i( 0, 0 ); glVertex2i( worldStart + i * HLINE + HLINE / 2, worldData[i].groundHeight + cgh[1] );
+ glTexCoord2i( 1, 0 ); glVertex2i( worldStart + i * HLINE + HLINE , worldData[i].groundHeight + cgh[1] );
+ glTexCoord2i( 1, 1 ); glVertex2i( worldStart + i * HLINE + HLINE , worldData[i].groundHeight - GRASS_HEIGHT );
+ glTexCoord2i( 0, 1 ); glVertex2i( worldStart + i * HLINE + HLINE / 2, worldData[i].groundHeight - GRASS_HEIGHT );
glEnd();
-
- cline[i].y-=(yoff-DRAW_Y_OFFSET);
}
- //glEnd();
+
glUseProgram(0);
glDisable(GL_TEXTURE_2D);
/*
- * Draw non-structure entities.
- */
- for(auto &part : particles){if(!part->behind)part->draw();}
- for(auto &n : current->npc){
- n->loc.y+=(yoff-DRAW_Y_OFFSET);
+ * Draw remaining entities.
+ */
+
+ std::for_each( particles.begin(), particles.end(), [](Particles part) { if ( !part.behind ) part.draw(); });
+
+ for ( auto &n : npc )
n->draw();
- n->loc.y-=(yoff-DRAW_Y_OFFSET);
- }
- for(auto &m : current->mob){
- m->loc.y+=(yoff-DRAW_Y_OFFSET);
+
+ for ( auto &m : mob )
m->draw();
- m->loc.y-=(yoff-DRAW_Y_OFFSET);
- }
- for(auto &o : current->object){
- if(o->alive){
- o->loc.y+=(yoff-DRAW_Y_OFFSET);
- o->draw();
- o->loc.y-=(yoff-DRAW_Y_OFFSET);
- }
- }
-
- /*
- * If we're drawing the closest/last world, handle and draw the player.
- */
+
+ for ( auto &o : object )
+ o->draw();
- if(current==this){
-
- /*
- * Calculate the line that the player is on
- */
-
- unsigned int ph = (p->loc.x + p->width / 2 - x_start) / HLINE;
-
- /*
- * If the player is on the ground, flatten the grass where the player is standing
- * by setting line.gs to false.
- */
-
- if(p->ground==1){
- for(i=0;i<lineCount-GEN_INC;i++){
- if(i < ph + 6 &&
- i > ph - 6 )
- cline[i].gs=false;
- else cline[i].gs=true;
- }
- }else{
- for(i=0;i<lineCount-GEN_INC;i++){
- cline[i].gs=true;
- }
- }
-
- /*
- * Draw the player.
- */
-
- p->draw();
-
+ /*
+ * Handle grass-squishing.
+ */
+
+ // calculate the line that the player is on
+ int ph = ( p->loc.x + p->width / 2 - worldStart ) / HLINE;
+
+ // flatten grass under the player if the player is on the ground
+ if ( p->ground ) {
+ for ( i = 0; i < (int)(worldData.size() - GROUND_HILLINESS); i++ )
+ worldData[i].grassUnpressed = !( i < ph + 6 && i > ph - 6 );
+ } else {
+ for ( i = 0; i < (int)(worldData.size() - GROUND_HILLINESS); i++ )
+ worldData[i].grassUnpressed = true;
}
-
- /*
- * Restore the inverted shading if it was inverted above.
- */
-
- shade*=-1;
-
+
/*
- * Draw the next closest world if it exists.
- */
-
- /*if(current->infront){
- yoff -= DRAW_Y_OFFSET;
- shade -= DRAW_SHADE;
-
- current=current->infront;
- goto LOOP2;
-
- }else{*/
-
- /*
- * If finished, reset the yoff and shade variables for the next call.
- */
-
- yoff=DRAW_Y_OFFSET;
- shade=0;
- //}
+ * Draw the player.
+ */
+
+ p->draw();
}
-void World::singleDetect(Entity *e){
+/**
+ * Handles physics and such for a single entity.
+ *
+ * This function is kept private, as World::detect() should be used instead to
+ * handle stuffs for all entities at once.
+ */
+
+void World::
+singleDetect( Entity *e )
+{
+ std::string killed;
unsigned int i,j;
int l;
@@ -795,12 +692,12 @@ void World::singleDetect(Entity *e){
* Kill any dead entities.
*/
- if(!e->alive||e->health<=0){
- for(i=0;i<entity.size();i++){
- if(entity[i]==e){
- switch(e->type){
+ if ( !e->alive || e->health <= 0 ) {
+ for ( i = 0; i < entity.size(); i++) {
+ if ( entity[i] == e ){
+ switch ( e->type ) {
case STRUCTURET:
- std::cout<<"Killed a building..."<<std::endl;
+ killed = "structure";
for(j=0;j<build.size();j++){
if(build[j]==e){
delete build[j];
@@ -810,7 +707,7 @@ void World::singleDetect(Entity *e){
}
break;
case NPCT:
- std::cout<<"Killed an NPC..."<<std::endl;
+ killed = "NPC";
for(j=0;j<npc.size();j++){
if(npc[j]==e){
delete npc[j];
@@ -820,7 +717,7 @@ void World::singleDetect(Entity *e){
}
break;
case MOBT:
- std::cout<<"Killed a mob..."<<std::endl;
+ killed = "mob";
/*for(j=0;j<mob.size();j++){
if(mob[j]==e){
delete mob[j];
@@ -830,7 +727,7 @@ void World::singleDetect(Entity *e){
}*/
break;
case OBJECTT:
- std::cout<<"Killed an object..."<<std::endl;
+ killed = "object";
for(j=0;j<object.size();j++){
if(object[j]==e){
delete object[j];
@@ -842,6 +739,7 @@ void World::singleDetect(Entity *e){
default:
break;
}
+ std::cout << "Killed a " << killed << "..." << std::endl;
entity.erase(entity.begin()+i);
return;
}
@@ -853,16 +751,17 @@ void World::singleDetect(Entity *e){
/*
* Handle only living entities.
*/
-
+
if(e->alive){
- if(e->type == MOBT && Mobp(e)->subtype == MS_TRIGGER)return;
+ if ( e->type == MOBT && Mobp(e)->subtype == MS_TRIGGER )
+ return;
/*
* Calculate the line that this entity is currently standing on.
*/
- l=(e->loc.x + e->width / 2 - x_start) / HLINE;
+ l=(e->loc.x + e->width / 2 - worldStart) / HLINE;
if(l < 0) l=0;
i = l;
if(i > lineCount-1) i=lineCount-1;
@@ -871,39 +770,11 @@ void World::singleDetect(Entity *e){
* If the entity is under the world/line, pop it back to the surface.
*/
- if(e->loc.y < line[i].y){
-
- /*
- * Check that the entity isn't trying to run through a wall.
- */
-
- //if(e->loc.y + e->height > line[i-(int)e->width/2/HLINE].y &&
- // e->loc.y + e->height > line[i+(int)e->width/2/HLINE].y ){
-
- e->loc.y=line[i].y - .001 * deltaTime;
- e->ground=true;
- e->vel.y=0;
-
- //}else{
-
- /*
- * Push the entity out of the wall if it's trying to go through it.
- */
-
- /*do{
- e->loc.x+=.001 * e->vel.x>0?-1:1;
-
- l=(e->loc.x - e->width / 2 - x_start) / HLINE;
- if(l < 0){
- std::cout<<"push kill lol "<<e->type<<std::endl;
- e->alive = false; return; }
- i = l;
- if(i > lineCount-1){
- std::cout<<"push kill lol "<<e->type<<std::endl;
- e->alive = false; return; }
- }while(line[i].y>e->loc.y+ e->height);
-
- }*/
+ if ( e->loc.y < worldData[i].groundHeight ) {
+
+ e->loc.y= worldData[i].groundHeight - .001 * deltaTime;
+ e->ground=true;
+ e->vel.y=0;
/*
* Handle gravity if the entity is above the line.
@@ -912,7 +783,7 @@ void World::singleDetect(Entity *e){
}else{
if(e->type == STRUCTURET && e->loc.y > 2000){
- e->loc.y = line[i].y;
+ e->loc.y = worldData[i].groundHeight;
e->vel.y = 0;
e->ground = true;
return;
@@ -924,129 +795,126 @@ void World::singleDetect(Entity *e){
* Insure that the entity doesn't fall off either edge of the world.
*/
- if(e->loc.x < x_start){ // Left bound
+ if(e->loc.x < worldStart){ // Left bound
e->vel.x=0;
- e->loc.x=(float)x_start + HLINE / 2;
+ e->loc.x=(float)worldStart + HLINE / 2;
- }else if(e->loc.x + e->width + HLINE > x_start + getWidth(this)){ // Right bound
+ }else if(e->loc.x + e->width + HLINE > worldStart + worldStart * -2){ // Right bound
e->vel.x=0;
- e->loc.x=x_start + getWidth(this) - e->width - HLINE;
+ e->loc.x=worldStart + worldStart * -2 - e->width - HLINE;
}
}
}
-void World::detect(Player *p){
-
- /*
- * Handle the player.
- */
+/**
+ * Handle entity logic for the world.
+ *
+ * This function runs World::singleDetect() for the player and every entity
+ * currently in a vector of this world. Particles and village entrance/exiting
+ * are also handled here.
+ */
+
+void World::
+detect( Player *p )
+{
+ int l;
- //auto pl = std::async(&World::singleDetect,this,p);
- std::thread(&World::singleDetect,this, p).detach();
+ // handle the player
+ std::thread( &World::singleDetect, this, p).detach();
- /*
- * Handle all remaining entities in this world.
- */
-
-//LOOOOP:
- for(auto &e : entity)
+ // handle other entities
+ for ( auto &e : entity )
std::thread(&World::singleDetect,this,e).detach();
- //hey->singleDetect(e);
- for(auto &part : particles){
- int l;
- unsigned int i;
- l=(part->loc.x + part->width / 2 - x_start) / HLINE;
- if(l < 0) l=0;
- i = l;
- if(i > lineCount-1) i=lineCount-1;
- if(part->loc.y < line[i].y){
- part->loc.y = line[i].y;
- part->vely = 0;
- part->velx = 0;
- part->canMove = false;
- }else{
- if(part->gravity && part->vely > -2)part->vely-=.003 * deltaTime;
- }
- }
- for(auto &b : build){
- switch(b->bsubtype){
- case FOUNTAIN:
- for(int r = 0; r < (rand()%25)+10;r++){
- addParticle( rand()%HLINE*3 + b->loc.x + b->width/2,
- b->loc.y + b->height,
- HLINE*1.25,
- HLINE*1.25,
- rand()%2 == 0?-(rand()%7)*.01:(rand()%7)*.01,
- ((4+rand()%6)*.05),
- {0,0,255},
- 2500);
-
- particles.back()->fountain = true;
- }
- break;
- case FIRE_PIT:
- for(int r = 0; r < (rand()%20)+10;r++){
- addParticle(rand()%(int)(b->width/2) + b->loc.x+b->width/4, b->loc.y+3*HLINE, HLINE, HLINE, rand()%2 == 0?-(rand()%3)*.01:(rand()%3)*.01,((4+rand()%6)*.005), {255,0,0}, 400);
- particles.back()->gravity = false;
- particles.back()->behind = true;
- }
- break;
- default: break;
+
+ // handle particles
+ for ( auto &part : particles ) {
+
+ // get particle's current world line
+ l = (part.loc.x + part.width / 2 - worldStart) / HLINE;
+
+ if ( l < 0 )
+ l = 0;
+
+ if ( l > (int)(lineCount - 1) )
+ l = lineCount - 1;
+
+ // handle ground collision
+ if ( part.loc.y < worldData[l].groundHeight ) {
+ part.loc.y = worldData[l].groundHeight;
+ part.vely = 0;
+ part.velx = 0;
+ part.canMove = false;
+ } else if ( part.gravity && part.vely > -2 )
+ part.vely -= .003 * deltaTime;
+ }
+
+ // handle particle creation
+ for ( auto &b : build ) {
+ switch ( b->bsubtype ) {
+ case FOUNTAIN:
+ for ( unsigned int r = (randGet() % 25) + 11; r--; ) {
+ addParticle(randGet() % HLINE * 3 + b->loc.x + b->width / 2, // x
+ b->loc.y + b->height, // y
+ HLINE * 1.25, // width
+ HLINE * 1.25, // height
+ randGet() % 7 * .01 * (randGet() % 2 == 0 ? -1 : 1), // vel.x
+ (4 + randGet() % 6) * .05, // vel.y
+ { 0, 0, 255 }, // RGB color
+ 2500 // duration (ms)
+ );
+
+ particles.back().fountain = true;
+ }
+ break;
+
+ case FIRE_PIT:
+ for(unsigned int r = (randGet() % 20) + 11; r--; ) {
+ addParticle(randGet() % (int)(b->width / 2) + b->loc.x + b->width / 4, // x
+ b->loc.y + 3 * HLINE, // y
+ HLINE, // width
+ HLINE, // height
+ randGet() % 3 * .01 * (randGet() % 2 == 0 ? -1 : 1), // vel.x
+ (4 + randGet() % 6) * .005, // vel.y
+ { 255, 0, 0 }, // RGB color
+ 400 // duration (ms)
+ );
+
+ particles.back().gravity = false;
+ particles.back().behind = true;
+ }
+ break;
+
+ default:
+ break;
}
}
- for(auto &v : village){
- if(p->loc.x > v.start.x && p->loc.x < v.end.x){
- if(!v.in){
- ui::passiveImportantText(5000,"Welcome to %s",v.name.c_str());
- v.in = true;
+ // draws the village welcome message if the player enters the village bounds
+ for ( auto &v : village ) {
+ if ( p->loc.x > v->start.x && p->loc.x < v->end.x ) {
+ if ( !v->in ) {
+ ui::passiveImportantText( 5000, "Welcome to %s", v->name.c_str() );
+ v->in = true;
}
- }else{
- v.in = false;
- }
+ } else
+ v->in = false;
}
-
- /*if(hey->infront){
- hey = hey->infront;
- goto LOOOOP;
- }*/
}
-void World::addStructure(BUILD_SUB sub, float x,float y, char *tex, const char *inside){
+void World::addStructure(BUILD_SUB sub, float x,float y, std::string tex, std::string inside){
build.push_back(new Structures());
build.back()->inWorld = this;
build.back()->textureLoc = tex;
+
build.back()->spawn(sub,x,y);
-
- if(inside)
- strcpy((build.back()->inside = new char[1 + strlen(inside)]),inside);
- else
- strcpy((build.back()->inside = new char[1]),"\0");
-
- //strcpy((build.back()->outside = new char[1 + strlen((char *)(currentXML+4))]),(char *)(currentXML+4));
+ build.back()->inside = inside;
+
entity.push_back(build.back());
}
-
-/*void World::addVillage(int bCount, int npcMin, int npcMax,const char *inside){
- std::cout << npcMin << ", " << npcMax << std::endl;
- //int xwasd;
- for(int i = 0; i < bCount; i++){
- addStructure(HOUSE,x_start + (i * 300),100,inside);
- std::cout<<"1\n";
- HERE:
- xwasd = (rand()%(int)x+1000*HLINE);
- for(auto &bu : build){
- if(xwasd > bu->loc.x && xwasd < bu->loc.x+bu->width)goto HERE;
- }
- std::cout<<"2\n";
- addStructure(t,HOUSE,xwasd,y,inside);
- std::cout<<"3\n";
- }
-}*/
void World::addMob(int t,float x,float y){
mob.push_back(new Mob(t));
@@ -1070,55 +938,37 @@ void World::addNPC(float x,float y){
entity.push_back(npc.back());
}
-void World::addObject(/*ITEM_ID i*/std::string in,const char *p, float x, float y){
+void World::addMerchant(float x, float y){
+ merchant.push_back(new Merchant());
+ merchant.back()->spawn(x,y);
+
+ npc.push_back(merchant.back());
+ entity.push_back(npc.back());
+}
+
+void World::addObject( std::string in, std::string p, float x, float y){
object.push_back(new Object(in,p));
object.back()->spawn(x,y);
entity.push_back(object.back());
}
-void World::addParticle(float x, float y, float w, float h, float vx, float vy, Color color, int d){
- particles.push_back(new 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 )
+{
+ particles.emplace_back( x, y, w, h, vx, vy, color, d );
+ particles.back().canMove = true;
}
void World::addLight(vec2 loc, Color color){
+ Light l;
if(light.size() < 64){
- light.push_back(Light());
- light.back().loc = loc;
- light.back().color = color;
+ l.loc = loc;
+ l.color = color;
+ light.push_back(l);
}
}
-/*void World::removeObject(Object i){
- object.delete[](i);
-}*/
-
-/*
- * The rest of these functions are explained well enough in world.h ;)
-*/
-
-/*void World::addLayer(unsigned int width){
- if(behind){
- behind->addLayer(width);
- return;
- }
- behind=new World();
- behind->generate(width);
- behind->infront=this;
- behind->star=star;
- behind->bgmObj=bgmObj;
- behind->bgTex=bgTex;
-}*/
-
-NPC *World::getAvailableNPC(void){
- for(auto &n : npc){
- if(n->aiFunc.empty())
- return n;
- }
- return (NPC *)NULL;
-}
-
char *World::setToLeft(const char *file){
if(toLeft)
delete[] toLeft;
@@ -1138,13 +988,20 @@ char *World::setToRight(const char *file){
return toRight;
}
-World *World::goWorldLeft(Player *p){
+World *World::
+goWorldLeft( Player *p )
+{
World *tmp;
- if(toLeft && p->loc.x < x_start + (int)HLINE * 15){
+
+ // check if player is at world edge
+ if(toLeft && p->loc.x < worldStart + HLINE * 15.0f){
+
+ // load world (`toLeft` conditional confirms existance)
tmp = loadWorldFromXML(toLeft);
- p->loc.x = -tmp->x_start - HLINE * 10;
- p->loc.y = tmp->line[tmp->lineCount - 1].y;
+ // adjust player location
+ p->loc.x = tmp->worldStart - HLINE * -10.0f;
+ p->loc.y = tmp->worldData[tmp->lineCount - 1].groundHeight;
return tmp;
}
@@ -1154,43 +1011,29 @@ World *World::goWorldLeft(Player *p){
World *World::goWorldRight(Player *p){
World *tmp;
- if(toRight && p->loc.x + p->width > -x_start - HLINE * 15){
+ if(toRight && p->loc.x + p->width > -worldStart - HLINE * 15){
tmp = loadWorldFromXML(toRight);
- p->loc.x = tmp->x_start + (int)HLINE * 10;
- p->loc.y = tmp->line[0].y;
+ p->loc.x = tmp->worldStart + HLINE * 10;
+ p->loc.y = GROUND_HEIGHT_MINIMUM;
return tmp;
}
return this;
}
-/*World *World::goWorldBack(Player *p){
- if(behind&&p->loc.x>(int)(0-getWidth(behind)/2)&&p->loc.x<getWidth(behind)/2){
- return behind;
- }
- return this;
-}
-
-World *World::goWorldFront(Player *p){
- if(infront&&p->loc.x>(int)(0-getWidth(infront)/2)&&p->loc.x<getWidth(infront)/2){
- return infront;
- }
- return this;
-}*/
-
-std::vector<char *>inside;
-World *World::goInsideStructure(Player *p){
+World *World::
+goInsideStructure( Player *p )
+{
World *tmp;
char *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 ){
- inside.push_back(new char[1 + strlen(currentXML)]);
- strcpy(inside.back(),(char *)(currentXML+4));
+ inside.push_back((std::string)(currentXML.c_str() + 4));
- tmp = loadWorldFromXML(b->inside);
+ tmp = loadWorldFromXML(b->inside.c_str());
ui::toggleBlackFast();
ui::waitForCover();
@@ -1200,16 +1043,17 @@ World *World::goInsideStructure(Player *p){
}
}
}else{
- strcpy((current = new char[strlen((char *)(currentXML + 4)) + 1]),(char *)(currentXML + 4));
- tmp = loadWorldFromXML(inside.back());
+ strcpy((current = new char[strlen((const char *)(currentXML.c_str() + 4)) + 1]),(const char *)(currentXML.c_str() + 4));
+ tmp = loadWorldFromXML(inside.back().c_str());
for(auto &b : tmp->build){
- if(!strcmp(current,b->inside)){
- p->loc.x = b->loc.x + (b->width / 2);
- delete[] inside.back();
+ if(!strcmp(current,b->inside.c_str())){
inside.pop_back();
ui::toggleBlackFast();
ui::waitForCover();
+
+ p->loc.x = b->loc.x + (b->width / 2);
+
ui::toggleBlackFast();
return tmp;
@@ -1223,18 +1067,14 @@ World *World::goInsideStructure(Player *p){
void World::addHole(unsigned int start,unsigned int end){
unsigned int i;
for(i=start;i<end;i++){
- line[i].y=0;
+ worldData[i].groundHeight = 0;
}
}
-int World::getTheWidth(void){
- World *hey=this;
-/*LOOP:
- if(hey->infront){
- hey=hey->infront;
- goto LOOP;
- }*/
- return -hey->x_start*2;
+int World::
+getTheWidth( void ) const
+{
+ return worldStart * -2;
}
void World::save(void){
@@ -1268,11 +1108,6 @@ void World::save(void){
out.close();
}
-#include <sstream>
-
-extern int commonAIFunc(NPC *);
-extern void commonTriggerFunc(Mob *);
-
void World::load(void){
std::string save,data,line;
const char *filedata;
@@ -1331,26 +1166,17 @@ IndoorWorld::IndoorWorld(void){
IndoorWorld::~IndoorWorld(void){
delete bgTex;
- delete[] star;
- delete[] line;
deleteEntities();
}
void IndoorWorld::generate(unsigned int width){ // Generates a flat area of width 'width'
- unsigned int i; // Used for 'for' loops
- lineCount=width+GEN_INC; // Sets line count to the desired width plus GEN_INC to remove incorrect line calculations.
+ lineCount=width+GROUND_HILLINESS; // Sets line count to the desired width plus GEN_INC to remove incorrect line calculations.
if(lineCount<=0)abort();
- line = new struct line_t[lineCount]; //(struct line_t *)calloc(lineCount,sizeof(struct line_t)); // Allocate memory for the array 'line'
- memset(line,0,lineCount*sizeof(struct line_t));
+ worldData = std::vector<WorldData> (lineCount, WorldData { false, {0,0}, INDOOR_FLOOR_HEIGHT, 0 });
- for(i=0;i<lineCount;i++){ // Indoor areas don't have to be directly on the ground (i.e. 0)...
- line[i].y=INDOOR_FLOOR_HEIGHT;
- }
- //behind=infront=NULL; // Set pointers to other worlds to NULL
- //toLeft=toRight=NULL; // to avoid accidental calls to goWorld... functions
- x_start=0-getWidth(this)/2+GEN_INC/2*HLINE; // Calculate x_start (explained in world.h)
+ worldStart = (width - GROUND_HILLINESS) * HLINE / 2 * -1;
}
void IndoorWorld::draw(Player *p){
@@ -1364,24 +1190,32 @@ void IndoorWorld::draw(Player *p){
glEnable(GL_TEXTURE_2D);
- GLfloat pointArray[light.size()][2];
- for(uint w = 0; w < light.size(); w++){
- pointArray[w][0] = light[w].loc.x - offset.x;
- pointArray[w][1] = light[w].loc.y;
+ std::unique_ptr<GLfloat[]> pointArrayBuf = std::make_unique<GLfloat[]> (2 * (light.size() + p->light));
+ auto pointArray = pointArrayBuf.get();
+
+ for ( i = 0; i < light.size(); i++ ) {
+ pointArray[2 * i ] = light[i].loc.x - offset.x;
+ pointArray[2 * i + 1] = light[i].loc.y;
}
- glUseProgram(shaderProgram);
- glUniform1i(glGetUniformLocation(shaderProgram, "sampler"), 0);
- glUniform1f(glGetUniformLocation(shaderProgram, "amb"), 0.0f);
- if(p->light){
- glUniform1i(glGetUniformLocation(shaderProgram, "numLight"), 1);
- glUniform2f(glGetUniformLocation(shaderProgram, "lightLocation"), p->loc.x - offset.x+SCREEN_WIDTH/2, p->loc.y);
- glUniform3f(glGetUniformLocation(shaderProgram, "lightColor"), 1.0f,1.0f,1.0f);
- }else if(!light.size()){
- glUniform1i(glGetUniformLocation(shaderProgram, "numLight"), 0);
- }else{
- glUniform1i(glGetUniformLocation(shaderProgram, "numLight"), light.size());
- glUniform2fv(glGetUniformLocation(shaderProgram, "lightLocation"), light.size(), (GLfloat *)&pointArray);
- glUniform3f(glGetUniformLocation(shaderProgram, "lightColor"), 1.0f,1.0f,1.0f);
+
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+
+ glUseProgram( shaderProgram );
+ glUniform1i( glGetUniformLocation( shaderProgram, "sampler"), 0 );
+ glUniform1f( glGetUniformLocation( shaderProgram, "amb" ), 0.3f );
+
+ if ( p->light ) {
+ pointArray[2 * (light.size() + 1) ] = (float)( p->loc.x + SCREEN_WIDTH / 2 );
+ pointArray[2 * (light.size() + 1) + 1] = (float)( p->loc.y );
+ }
+
+ if ( light.size() + (int)p->light == 0)
+ glUniform1i( glGetUniformLocation( shaderProgram, "numLight"), 0);
+ else {
+ glUniform1i ( glGetUniformLocation( shaderProgram, "numLight" ), light.size() + (int)p->light );
+ glUniform2fv( glGetUniformLocation( shaderProgram, "lightLocation"), light.size() + (int)p->light, pointArray );
+ glUniform3f ( glGetUniformLocation( shaderProgram, "lightColor" ), 1.0f, 1.0f, 1.0f );
}
bgTex->bind(0);
@@ -1389,13 +1223,11 @@ void IndoorWorld::draw(Player *p){
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); //for the t direction
glColor4ub(255,255,255,255);
- glBegin(GL_QUADS);
- //for(j = x_start - SCREEN_WIDTH / 2;j < -x_start + SCREEN_WIDTH / 2; j += 512){
- glTexCoord2i(0,1); glVertex2i( x_start - SCREEN_WIDTH / 2,0);
- glTexCoord2i((-x_start*2+SCREEN_WIDTH)/512,1);glVertex2i(-x_start + SCREEN_WIDTH / 2,0);
- glTexCoord2i((-x_start*2+SCREEN_WIDTH)/512,0);glVertex2i(-x_start + SCREEN_WIDTH / 2,SCREEN_HEIGHT);
- glTexCoord2i(0,0); glVertex2i( x_start - SCREEN_WIDTH / 2,SCREEN_HEIGHT);
- //}
+ glBegin(GL_QUADS);
+ glTexCoord2i(0,1); glVertex2i( worldStart - SCREEN_WIDTH / 2,0);
+ glTexCoord2i((-worldStart*2+SCREEN_WIDTH)/512,1);glVertex2i(-worldStart + SCREEN_WIDTH / 2,0);
+ glTexCoord2i((-worldStart*2+SCREEN_WIDTH)/512,0);glVertex2i(-worldStart + SCREEN_WIDTH / 2,SCREEN_HEIGHT);
+ glTexCoord2i(0,0); glVertex2i( worldStart - SCREEN_WIDTH / 2,SCREEN_HEIGHT);
glEnd();
glUseProgram(0);
@@ -1422,14 +1254,14 @@ void IndoorWorld::draw(Player *p){
glUseProgram(shaderProgram);
glUniform1i(glGetUniformLocation(shaderProgram, "sampler"), 0);
glBegin(GL_QUADS);
- for(;i < ie - GEN_INC;i++){
+ for(;i < ie - GROUND_HILLINESS;i++){
safeSetColor(150,100,50);
- x = x_start + i * HLINE;
- glVertex2i(x ,line[i].y);
- glVertex2i(x + HLINE,line[i].y);
- glVertex2i(x + HLINE,line[i].y - 50);
- glVertex2i(x ,line[i].y - 50);
+ x = worldStart + i * HLINE;
+ glVertex2i(x ,worldData[i].groundHeight);
+ glVertex2i(x + HLINE,worldData[i].groundHeight);
+ glVertex2i(x + HLINE,worldData[i].groundHeight - 50);
+ glVertex2i(x ,worldData[i].groundHeight - 50);
}
glEnd();
glUseProgram(0);
@@ -1438,15 +1270,14 @@ void IndoorWorld::draw(Player *p){
* Draw all entities.
*/
- for(auto &part : particles) part->draw();
- for(auto &e : entity) e->draw();
- p->draw();
-}
+ for ( auto &part : particles )
+ part.draw();
-extern bool inBattle;
+ for ( auto &e : entity )
+ e->draw();
-std::vector<World *> battleNest;
-std::vector<vec2> battleNestLoc;
+ p->draw();
+}
Arena::Arena(World *leave,Player *p,Mob *m){
generate(800);
@@ -1454,24 +1285,16 @@ Arena::Arena(World *leave,Player *p,Mob *m){
inBattle = true;
mmob = m;
- //exit = leave;
- //pxy = p->loc;
+ mmob->aggressive = false;
mob.push_back(m);
entity.push_back(m);
battleNest.push_back(leave);
battleNestLoc.push_back(p->loc);
-
- star = new vec2[100];
- memset(star,0,100 * sizeof(vec2));
}
Arena::~Arena(void){
- delete bgTex;
- delete[] star;
- delete[] line;
-
deleteEntities();
}
@@ -1488,30 +1311,29 @@ World *Arena::exitArena(Player *p){
p->loc = battleNestLoc.back();
battleNestLoc.pop_back();
- //mmob->alive = false;
+
+ mob.clear();
+ mmob->alive = false;
+
return tmp;
}else{
return this;
}
}
-#include <tinyxml2.h>
-using namespace tinyxml2;
-
-char *currentXML = NULL;
-
-extern World *currentWorld;
-
-World *loadWorldFromXML(const char *path){
- if(currentXML){
+World *loadWorldFromXML(std::string path){
+ if ( !currentXML.empty() )
currentWorld->save();
- delete[] currentXML;
- }
-
+
return loadWorldFromXMLNoSave(path);
}
-World *loadWorldFromXMLNoSave(const char *path){
+/**
+ * Loads a world from the given XML file.
+ */
+
+World *
+loadWorldFromXMLNoSave( std::string path ) {
XMLDocument xml;
XMLElement *wxml;
XMLElement *vil;
@@ -1521,59 +1343,55 @@ World *loadWorldFromXMLNoSave(const char *path){
bool dialog,Indoor;
const char *ptr,*name;
-
- unsigned int size = 5 + strlen(path);
+
+ currentXML = (std::string)"xml/" + path;
- if(currentXML)
- delete[] currentXML;
- memset((currentXML = new char[size]),0,size);
- strcpy(currentXML,"xml/");
- strcat(currentXML,path);
-
- xml.LoadFile(currentXML);
+ xml.LoadFile(currentXML.c_str());
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();
}
while(wxml){
name = wxml->Name();
+
if(!strcmp(name,"link")){
if((ptr = wxml->Attribute("left")))
tmp->setToLeft(ptr);
else if((ptr = wxml->Attribute("right")))
tmp->setToRight(ptr);
- else abort();
+ else
+ abort();
}else if(!strcmp(name,"style")){
- tmp->setStyle(wxml->Attribute("folder"));
- tmp->setBackground((WORLD_BG_TYPE)wxml->UnsignedAttribute("background"));
- tmp->setBGM(wxml->Attribute("bgm"));
+ tmp->setStyle(wxml->StrAttribute("folder"));
+ tmp->setBackground((WorldBGType)wxml->UnsignedAttribute("background"));
+ tmp->setBGM(wxml->StrAttribute("bgm"));
}else if(!strcmp(name,"generation")){
if(!strcmp(wxml->Attribute("type"),"Random")){
if(Indoor)
((IndoorWorld *)tmp)->generate(wxml->UnsignedAttribute("width"));
- else
+ else {
+
tmp->generate(wxml->UnsignedAttribute("width"));
- }else if(Indoor){
+ }
+ }else if(Indoor)
abort();
- }
}else if(!strcmp(name,"mob")){
unsigned int type;
-
type = wxml->UnsignedAttribute("type");
if(wxml->QueryFloatAttribute("x",&spawnx) != XML_NO_ERROR)
- tmp->addMob(type,getRand() % tmp->getTheWidth() / 2,100);
+ tmp->addMob(type,0,100);
else
tmp->addMob(type,spawnx,wxml->FloatAttribute("y"));
-
if(wxml->QueryBoolAttribute("aggressive",&dialog) == XML_NO_ERROR)
tmp->mob.back()->aggressive = dialog;
@@ -1581,7 +1399,7 @@ World *loadWorldFromXMLNoSave(const char *path){
const char *npcname;
if(wxml->QueryFloatAttribute("x",&spawnx) != XML_NO_ERROR)
- tmp->addNPC(getRand() % tmp->getTheWidth() / 2.0f,100);
+ tmp->addNPC(0,100);
else
tmp->addNPC(spawnx,wxml->FloatAttribute("y"));
@@ -1598,14 +1416,13 @@ World *loadWorldFromXMLNoSave(const char *path){
else tmp->npc.back()->dialogIndex = 9999;
}else if(!strcmp(name,"structure")){
- ptr = wxml->Attribute("inside");
tmp->addStructure((BUILD_SUB)wxml->UnsignedAttribute("type"),
wxml->QueryFloatAttribute("x",&spawnx) != XML_NO_ERROR ?
getRand() % tmp->getTheWidth() / 2.0f :
spawnx,
100,
- (char*)wxml->Attribute("texture"),
- ptr);
+ wxml->StrAttribute("texture"),
+ wxml->StrAttribute("inside"));
}else if(!strcmp(name,"trigger")){
tmp->addMob(MS_TRIGGER,wxml->FloatAttribute("x"),0,commonTriggerFunc);
tmp->mob.back()->heyid = wxml->Attribute("id");
@@ -1614,35 +1431,74 @@ World *loadWorldFromXMLNoSave(const char *path){
wxml = wxml->NextSiblingElement();
}
+ Village *vptr;
+
if(vil){
- tmp->village.push_back(vil->Attribute("name"));
+ tmp->village.push_back(new Village(vil->Attribute("name"), tmp));
+ vptr = tmp->village.back();
vil = vil->FirstChildElement();
}
while(vil){
name = vil->Name();
- randx = getRand() % tmp->getTheWidth() - (tmp->getTheWidth() / 2.0f);
+ randx = 0;
+ //static BuySell bs;
/**
* READS DATA ABOUT STRUCTURE CONTAINED IN VILLAGE
*/
+
if(!strcmp(name,"structure")){
- ptr = vil->Attribute("inside");
tmp->addStructure((BUILD_SUB)vil->UnsignedAttribute("type"),
+ vil->QueryFloatAttribute("x", &spawnx) != XML_NO_ERROR ? randx : spawnx,
+ 100,
+ vil->StrAttribute("texture"),
+ vil->StrAttribute("inside"));
+ }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);
+ vil->StrAttribute("texture"),
+ vil->StrAttribute("inside"));
+ tmp->addMerchant(0,100);
+ if(vil->FirstChildElement("buy")){
+ std::cout << "Buy" << std::endl;
+ //Trade goodMeme(1,"Dank MayMay",1,"Sword");
+ //tmp->merchant.back()->trade.push_back(Trade());
+ }if(vil->FirstChildElement("sell")){
+ std::cout << "Sell" << std::endl;
+ }if(vil->FirstChildElement("trade")){
+ std::cout << "Trade" << std::endl;
+ tmp->merchant.back()->trade.push_back(Trade(vil->FirstChildElement("trade")->IntAttribute("quantity"),
+ vil->FirstChildElement("trade")->Attribute("item"),
+ vil->FirstChildElement("trade")->IntAttribute("quantity1"),
+ vil->FirstChildElement("trade")->Attribute("item1")));
+ }
+ strcpy(tmp->merchant.back()->name,"meme");
- tmp->village.back().build.push_back(tmp->build.back());
+ }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,
+ vil->StrAttribute("texture"),
+ vil->StrAttribute("inside"));
+ }
}
- 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
@@ -1656,4 +1512,12 @@ World *loadWorldFromXMLNoSave(const char *path){
}
return tmp;
-} \ No newline at end of file
+
+}
+
+Village::Village(const char *meme, World *w){
+ name = meme;
+ start.x = w->getTheWidth() / 2.0f;
+ end.x = -start.x;
+ in = false;
+}