]> code.bitgloo.com Git - clyne/gamedev.git/commitdiff
hills
authorClyne Sullivan <tullivan99@gmail.com>
Tue, 15 Mar 2016 12:43:44 +0000 (08:43 -0400)
committerClyne Sullivan <tullivan99@gmail.com>
Tue, 15 Mar 2016 12:43:44 +0000 (08:43 -0400)
Changelog
include/world.h
main.cpp
src/entities.cpp
src/inventory.cpp
src/ui.cpp
src/world.cpp
xml/playerSpawnHill1.xml
xml/playerSpawnHill1_Building1.xml
xml/playerSpawnHill2.xml

index 795aa0d00c9395a77b8e842cdc5cd883acb10b25..c40e85146c33483e191208caaeeab11cb6cb96ff 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -44,7 +44,7 @@
        - successfully ran game 200 entities
        - improved debug screen
        - added mouse interaction w/ NPCs
-       
+
 9/30/2015:
 ==========
 
        - began work on giving names to NPCs
        - began working on config file
        - created a bug file
-       
+
        - added displaying of entity names on mouse hover
        - found more fonts
-       
+
 10/1/2015:
 ==========
 
 
        - fixed delaying quest assignments until dialog is closed
        - checked and secured errors in malloc/calloc calls
-       
+
 10/19/2015:
 ===========
 
        - fixed malloc/strlen bug that crashes the game on some linux systems
        - broke andy's linux system on his laptop, allowing for test game build on Windows
        - began extensive documentation in main.cpp
-       
+
 10/20/2015:
 ===========
 
        - andy's laptop 'can' boot
        - added 200+ lines of documentation to main.cpp
-       
+
 10/21/2015:
 ===========
 
        - successfully build game on 32-bit Windows (game crashes on execution)
        - removed npc array; NPCs are now created in the entity array
        - created a basic texture handling library
-       
+
 10/23/2015:
 ===========
 
        - fixed entity initialization
        - added multiple mobs
        - improved texture handling
-       
+
 10/26/2015:
 ===========
 
        - added typewriter-esque text drawing
        - documented ui.h
        - continued work on GLSL shaders
-       
+
 11/4/2015:
 ==========
 
        - added drawing/handling of entities on all layers at all times
        - removed building entering/exiting
        - andy broke SDL cuz he's bad
-       
+
 11/10/2015:
 ===========
 
        - minor bug fixes
        - began working on arenas
        - began working on cutscene triggers
-       
+
 11/17/2015:
 ===========
 
 
        - texture loaded tracks loaded textures to prevent re-loading (frees resources)
        - continued work on things finished the following day (11/20) :)
-       
+
 11/20/2015:
 ===========
 
        - imrpoved BGM handling
        - continued work on particles, made a fountain
        - added sanic
-       
+
        ~ Broke 5000 lines of code/doc, now with some file Doxygen'd
 
 12/14/2015:
 
        - can save NPCs and Structures
        - more shadering
-       
+
 1/6/2016:
 =========
 
        - flashlight!
        - XML-scripted worlds!!!
        - !!!!!!!!!!!!!!!!!!!!!!!!
-       
+
 1/7/2016:
 =========
 
        - xml'd npc and mob spawning
        - xml'd npc dialogs
        - drafted page xml
-       
+
 1/11/2016:
 ==========
 
        - xml'ing indoors
        - shaderssss
        - more music
-       
+
 1/13/2016:
 ==========
 
        - pondered on non-random generation
        - fixed some drawing issues
        - made spritesheet for easier solid-color-texture drawing
-       
+
        - began to incorporate XML into the world class for dynamic world loading...
 
 1/16/2016:
 
        - wrote paper regarding what we've learned, and where we're at
        - ported game to Windows, left EXE and DLLs in repo
-       
+
 2/1/2016:
 =========
 
        - partially fixed text drawing
        - XML'd quest checking, working on quest requirements
        - worked on XML'ing villages
-       
+
 2/9/2016:
 =========
 
        - mob deaths are saved
        - fixed building spawning
        - volumes are better
-       
+
        ~ 5 month Changelog anniversary!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 2/23/2016:
        - arenas work
        - cleaned up world codes
        - andy got here
-       
+
        ~ Total of 7,379 lines of code!
 
 3/8/2016:
        - pages are XMLable and can be drawn
        - dialogs are cool with threads
        - better lighting
+
+3/14/2016:
+==========
+
+       - began implementing hills in worlds
+       - more inventory stuffs
+
+3/15/2016:
+==========
+
+       - finished hills, fixed hill collision physics
+       - fixed player repositioning when switching worlds
+       - XML'd tickCount setting
+       - even more inventory stuffs (side panes)
index a60eab6332b05d6580b0aab3298feac2dbbefc2f..55c08f5e32dca8ccee989705e03c0f16a0342c31 100644 (file)
@@ -421,8 +421,15 @@ public:
        
        void addHole(unsigned int start,unsigned int end);
        
-       /*
-        *      Get's the world's width.
+       /**
+        * Adds a hill to the world, given the peak's coordinates and how wide the
+        * hill can be.
+        */
+       
+       void addHill( ivec2 peak, unsigned int width );
+       
+       /**
+        * Gets the world's width.
         */
        
        int getTheWidth(void) const;
index f9282c43c50aa758b596682eee46eeca233e23e3..6e58e1c0639b6fc09b8cc16c1b69bfec2c1cac52 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -104,7 +104,7 @@ GLuint fragShader;
 /**
  * TODO
  */
+
 GLuint shaderProgram;
 
 /**
@@ -202,9 +202,9 @@ void mainLoop(void);
 int main(int argc, char *argv[]){
        (void)argc;
        (void)argv;
-       
+
        static SDL_GLContext mainGLContext = NULL;
-       
+
        gameRunning = false;
 
        /**
@@ -307,13 +307,13 @@ int main(int argc, char *argv[]){
                std::cout << "GLEW was not able to initialize! Error: " << glewGetErrorString(err) << std::endl;
                return -1;
        }
-       
+
        /*
         * Initialize the random number generator. At the moment, initRand is a macro pointing to libc's
         * srand, and its partner getRand points to rand. This is because having our own random number
         * generator may be favorable in the future, but at the moment is not implemented.
         */
-       
+
        initRand(millis());
 
        /*
@@ -321,24 +321,24 @@ int main(int argc, char *argv[]){
         * setup the alpha channel for textures/transparency, and finally hide the system's mouse
         * cursor so that we may draw our own.
         */
-       
+
        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
        //SDL_GL_SetSwapInterval(0);
-       
+
        glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
-       
+
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       
+
        SDL_ShowCursor(SDL_DISABLE);
 
        Texture::initColorIndex();
        initEntity();
-       
+
        /*
         * Initializes our shaders so that the game has shadows.
         */
-       
+
        std::cout << "Initializing shaders!" << std::endl;
 
        const GLchar *shaderSource = readFile("test.frag");
@@ -353,17 +353,17 @@ int main(int argc, char *argv[]){
 
        glGetShaderiv(fragShader, GL_COMPILE_STATUS, &bufferln);
        glGetShaderiv(fragShader, GL_INFO_LOG_LENGTH, &logLength);
-       
+
        std::vector<char> fragShaderError ((logLength > 1) ? logLength : 1);
-       
+
        glGetShaderInfoLog(fragShader, logLength, NULL, &fragShaderError[0]);
        std::cout << &fragShaderError[0] << std::endl;
-       
+
        if(bufferln == GL_FALSE){
                std::cout << "Error compiling shader" << std::endl;
        }
 
-       shaderProgram = glCreateProgram();              
+       shaderProgram = glCreateProgram();
        glAttachShader(shaderProgram, fragShader);
        glLinkProgram(shaderProgram);
        glValidateProgram(shaderProgram);
@@ -373,18 +373,18 @@ int main(int argc, char *argv[]){
     std::vector<char> programError( (logLength > 1) ? logLength : 1 );
     glGetProgramInfoLog(shaderProgram, logLength, NULL, &programError[0]);
     std::cout << &programError[0] << std::endl;
-                       
+
        delete[] shaderSource;
-       
+
        glEnable(GL_MULTISAMPLE);
-       
+
        /*
         * Create all the worlds, entities, mobs, and the player. This function is defined in
         * src/gameplay.cpp
         */
-        
+
        fadeIntensity = 250;
-       
+
        initEverything();
 
        if(!currentWorld){
@@ -403,40 +403,40 @@ int main(int argc, char *argv[]){
 
        invUI = Texture::loadTexture("assets/invUI.png" );
        mouseTex = Texture::loadTexture("assets/mouse.png");
-       
+
        initInventorySprites();
-       
+
        /**************************
        ****     GAMELOOP      ****
        **************************/
-       
+
        std::cout << "Num threads: " << std::thread::hardware_concurrency() << std::endl;
 
        //currentWorld->mob.back()->followee = player;
-       
+
        gameRunning = true;
        while(gameRunning){
                mainLoop();
        }
-       
+
        /**************************
        ****   CLOSE PROGRAM   ****
        **************************/
-       
+
     /*
      * Close the window and free resources
      */
-    
+
     Mix_HaltMusic();
     Mix_CloseAudio();
-    
+
     destroyInventory();
        ui::destroyFonts();
     Texture::freeTextures();
-    
+
     SDL_GL_DeleteContext(mainGLContext);
     SDL_DestroyWindow(window);
-    
+
     return 0; // Calls everything passed to atexit
 }
 
@@ -451,20 +451,20 @@ static float debugY=0;
 
 void mainLoop(void){
        static unsigned int debugDiv=0;                 // A divisor used to update the debug menu if it's open
-       
+
        static unsigned int prevTime    = 0,    // Used for timing operations
                                                currentTime = 0,        //
                                                prevPrevTime= 0;        //
        World *prev;
-    
+
        if(!currentTime)                                                // Initialize currentTime if it hasn't been
                currentTime=millis();
-       
+
        /*
         * Update timing values. This is crucial to calling logic and updating the window (basically
         * the entire game).
         */
-       
+
        prevTime        = currentTime;
        currentTime = millis();
        deltaTime       = currentTime - prevTime;
@@ -477,7 +477,7 @@ void mainLoop(void){
         */
 
        prev = currentWorld;
-       
+
 
        //pool.Enqueue(ui::handleEvents);
        ui::handleEvents();
@@ -496,23 +496,23 @@ void mainLoop(void){
        /*
         * Update player and entity coordinates.
         */
-       
+
        /*pool.Enqueue([](){
                currentWorld->update(player,deltaTime);
        });*/
-       
+
        currentWorld->update(player,deltaTime);
-    
+
        /*
         * Update debug variables if necessary
         */
-       
+
        if ( ++debugDiv == 20 ) {
                debugDiv=0;
-               
+
                if ( deltaTime )
                        fps = 1000 / deltaTime;
-               else if(!(debugDiv%10))
+               if(!(debugDiv%10))
                        debugY = player->loc.y;
        }
 MENU:
@@ -520,12 +520,12 @@ MENU:
 }
 
 void render(){
-       
+
         /*
          *     This offset variable is what we use to move the camera and locked
          *     objects on the screen so they always appear to be in the same relative area
          */
-       
+
        offset.x = player->loc.x + player->width/2;
        offset.y = SCREEN_HEIGHT/2;
 
@@ -533,7 +533,7 @@ void render(){
         * If the camera will go off of the left  or right of the screen we want to lock it so we can't
         * see past the world render
         */
-       
+
        if(currentWorld->getTheWidth() < (int)SCREEN_WIDTH){
                offset.x = 0;
        }else{
@@ -542,7 +542,7 @@ void render(){
                if(player->loc.x + player->width + SCREEN_WIDTH/2 > currentWorld->getTheWidth() *  0.5f)
                        offset.x = ((currentWorld->getTheWidth() *  0.5f) - SCREEN_WIDTH / 2) - player->width / 2;
        }
-       
+
        if(player->loc.y > SCREEN_HEIGHT/2)
                offset.y = player->loc.y + player->height;
 
@@ -558,7 +558,7 @@ void render(){
         *
         *      glMatrixMode    This changes our current stacks mode so the drawings below
         *                                      it can take on certain traits.
-        *      
+        *
         *      GL_PROJECTION   This is the matrix mode that sets the cameras position,
         *                                      GL_PROJECTION is made up of a stack with two matrices which
         *                                      means we can make up to 2 seperate changes to the camera.
@@ -582,7 +582,7 @@ void render(){
         *      glLoadIdentity  This scales the current matrix back to the origin so the
         *                                      translations are seen normally on a stack.
         */
-       
+
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        glLoadIdentity();
@@ -591,7 +591,7 @@ void render(){
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glLoadIdentity();
-       
+
        /*
         * glPushAttrib         This passes attributes to the renderer so it knows what it can
         *                                      render. In our case, GL_DEPTH_BUFFER_BIT allows the renderer to
@@ -602,14 +602,14 @@ void render(){
         * glClear                      This clears the new matrices using the type passed. In our case:
         *                                      GL_COLOR_BUFFER_BIT allows the matrices to have color on them
         */
-       
+
        glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_LIGHTING_BIT );
        glClear(GL_COLOR_BUFFER_BIT);
 
        /**************************
        **** RENDER STUFF HERE ****
        **************************/
-               
+
        /*
         * Call the world's draw function, drawing the player, the world, the background, and entities. Also
         * draw the player's inventory if it exists.
@@ -622,7 +622,7 @@ void render(){
        /*
         * Calculate the player's hand angle.
         */
-        
+
        handAngle = atan((ui::mouse.y - (player->loc.y + player->height/2)) / (ui::mouse.x - player->loc.x + player->width/2))*180/PI;
        if(ui::mouse.x < player->loc.x){
                if(handAngle <= 0)
@@ -631,21 +631,21 @@ void render(){
                        handAngle+=180;
                }
        }
-       
+
        if(ui::mouse.x > player->loc.x && ui::mouse.y < player->loc.y+player->height/2 && handAngle <= 0)
                handAngle = 360 + handAngle;
 
-       
+
        /*
         * Draw the player's inventory.
         */
-       
+
        player->inv->draw();
 
        /*
         * Here we draw a black overlay if it's been requested.
         */
-       
+
        if(fadeIntensity){
                if(fadeWhite)
                        safeSetColorA(255,255,255,fadeIntensity);
@@ -662,7 +662,7 @@ void render(){
        /*
         * Draw UI elements. This includes the player's health bar and the dialog box.
         */
-       
+
        ui::draw();
 
        /*
@@ -670,7 +670,7 @@ void render(){
         */
 
        if(ui::debug){
-               
+
                ui::putText(offset.x-SCREEN_WIDTH/2,
                                        (offset.y+SCREEN_HEIGHT/2)-ui::fontSize,
                                        "FPS: %d\nG:%d\nRes: %ux%u\nE: %d\nPOS: (x)%+.2f\n     (y)%+.2f\nTc: %u\nHA: %+.2f\nPl: %d\n Vol: %f",
@@ -686,7 +686,7 @@ void render(){
                                        player->light,
                                        VOLUME_MASTER
                                        );
-               
+
                if(ui::posFlag){
                        glBegin(GL_LINES);
                                glColor3ub(255,0,0);
@@ -722,7 +722,7 @@ void render(){
                glTexCoord2f(0,1);glVertex2i(ui::mouse.x                        ,ui::mouse.y-HLINE*5    );
        glEnd();
        glDisable(GL_TEXTURE_2D);
-       
+
        /**************************
        ****  END RENDERING   ****
        **************************/
@@ -757,7 +757,7 @@ void logic(){
         *      Run the world's detect function. This handles the physics of the player and any entities
         *      that exist in this world.
         */
-       
+
        currentWorld->detect(player);
        if(player->loc.y<.02)gameRunning=false;
 
@@ -766,10 +766,10 @@ void logic(){
         *      basically runs their AI functions depending on what type of entity they are. For NPCs,
         *      click detection is done as well for NPC/player interaction.
         */
-        
+
        for(auto &n : currentWorld->npc){
                if(n->alive){
-                       
+
                        /*
                         *      Make the NPC 'wander' about the world if they're allowed to do so.
                         *      Entity->canMove is modified when a player interacts with an NPC so
@@ -778,9 +778,9 @@ void logic(){
 
                        if(n->canMove)
                                n->wander((rand() % 120 + 30));
-                       
+
                        /*if(!player->inv->usingi) n->hit = false;
-                       
+
                        if(player->inv->usingi && !n->hit && player->inv->detectCollision((vec2){n->loc.x, n->loc.y},(vec2){n->loc.x+n->width,n->loc.y+n->height})){
                                n->health -= 25;
                                n->hit = true;
@@ -791,7 +791,7 @@ void logic(){
                                                currentWorld->addParticle(rand()%HLINE*3 + n->loc.x - .05f,n->loc.y + n->height*.5, HLINE,HLINE, -(rand()%10)*.01,((rand()%10)*.01-.05), {(rand()%75)+10/100.0f,0,0}, 10000);
                                }
                        }*/
-                       
+
                        /*
                         *      Don't bother handling the NPC if another has already been handled.
                         */
@@ -848,7 +848,7 @@ void logic(){
                        }else n->near=false;
                }
        }
-       
+
        for(auto &m : currentWorld->mob){
                if(m->alive){
 
@@ -873,7 +873,7 @@ void logic(){
                        }
                }
        }
-       
+
        if(!objectInteracting){
                for(auto &o : currentWorld->object){
                        if(o->alive){
@@ -898,11 +898,11 @@ void logic(){
                        }
                }
        }
-       
+
        /*
         *      Switch between day and night (SUNNY and DARK) if necessary.
         */
-        
+
        if(!(tickCount%DAY_CYCLE)||!tickCount){
                if ( weather == WorldWeather::Sunny )
                        weather = WorldWeather::Dark;
@@ -921,7 +921,7 @@ void logic(){
        /*
         *      Transition to and from black if necessary.
        */
-       
+
        if(fadeEnable){
                         if(fadeIntensity < 150)fadeIntensity+=fadeFast?40:10;
                else if(fadeIntensity < 255)fadeIntensity+=fadeFast?20:5;
index 8a1042866b0563e7a1bc2981d01ffde3a73701dd..7d906ea1a68f27b4fffca08f8275d5f0b866a92a 100644 (file)
@@ -562,17 +562,19 @@ void Mob::wander(int timeRun){
        if(aggressive && !YAYA &&
           player->loc.x + (width / 2)  > loc.x && player->loc.x + (width / 2)  < loc.x + width  &&
           player->loc.y + (height / 3) > loc.y && player->loc.y + (height / 3) < loc.y + height ){
-               Arena *a = new Arena(currentWorld,player,this);
-               a->setStyle("");
-               a->setBackground( WorldBGType::Forest );
-               a->setBGM("assets/music/embark.wav");
+               if ( !ui::dialogBoxExists ) {
+                       Arena *a = new Arena(currentWorld,player,this);
+                       a->setStyle("");
+                       a->setBackground( WorldBGType::Forest );
+                       a->setBGM("assets/music/embark.wav");
                
-               ui::toggleWhiteFast();
-               YAYA = true;
-               ui::waitForCover();
-               YAYA = false;
-               currentWorld = a;
-               ui::toggleWhiteFast();
+                       ui::toggleWhiteFast();
+                       YAYA = true;
+                       ui::waitForCover();
+                       YAYA = false;
+                       currentWorld = a;
+                       ui::toggleWhiteFast();
+               }
        }
        
        switch(subtype){
index e82d99e49cb77e6f4fec17bf1a44dad8fd5df84c..795fb551bad3ba7a76e1751d3aee442a57306783 100644 (file)
@@ -142,12 +142,12 @@ const char *getItemTexturePath(std::string name){
 }
 
 GLuint getItemTexture(std::string name){
-       for(auto &i : itemMap){
-               if(i->name == name)
-                       return Texture::loadTexture(i->texloc);
+       for ( int i = itemMap.size(); i--; ) {
+               if ( itemMap[i]->name == name )
+                       return itemtex[i];
        }
-
-       return Texture::loadTexture("assets/items/ITEM_TEST.png");
+       DEBUG_printf("Failed to find texture for item %s!", name.c_str() );
+       return 0;
 }
 
 float getItemWidth(std::string name){
index 50ae9de33289732d8d807f25a23b3bd57c7847f0..414823820c8fb7f854f5f43951063cabeec248ea 100644 (file)
@@ -706,7 +706,7 @@ namespace ui {
                        
                                glColor3ub(255,255,255);
                                glBegin(GL_LINE_STRIP);
-                                       glVertex2f(x-1                                    ,y+1);
+                                       glVertex2f(x-1                             ,y+1);
                                        glVertex2f(x+1+(SCREEN_WIDTH/3),y+1);
                                        glVertex2f(x+1+(SCREEN_WIDTH/3),y-1-SCREEN_HEIGHT*.6);
                                        glVertex2f(x-1,y-1-SCREEN_HEIGHT*.6);
index af28ac5919a1ec3ead995f6632aecb03c792d10f..097847f68f2b1cbfeefbf3a6cedaa4aa4691b9f5 100644 (file)
@@ -66,10 +66,10 @@ const std::string bgPaths[2][9]={
 
 const std::string buildPaths[] = {
     "townhall.png",
-       "house1.png", 
-    "house2.png", 
-    "house1.png", 
-    "house1.png", 
+       "house1.png",
+    "house2.png",
+    "house1.png",
+    "house1.png",
     "fountain1.png",
     "lampPost1.png",
        "brazzier.png"
@@ -88,7 +88,7 @@ const float bgDraw[4][3]={
 
 /**
  * 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.
  */
@@ -101,7 +101,7 @@ setBackground( WorldBGType bgt )
        case WorldBGType::Forest:
                bgTex = new Texturec( bgFiles );
                break;
-        
+
        case WorldBGType::WoodHouse:
                bgTex = new Texturec( bgFilesIndoors );
                break;
@@ -114,7 +114,7 @@ setBackground( WorldBGType bgt )
 
 /**
  * Sets the world's style.
- * 
+ *
  * The world's style will determine what sprites are used for things like\
  * generic structures.
  */
@@ -123,25 +123,25 @@ 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 ( 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] );
 }
 
 /**
  * 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.
@@ -151,14 +151,14 @@ World::
 World( void )
 {
     bgmObj = NULL;
-    
+
        toLeft = NULL;
        toRight = NULL;
 }
 
 /**
  * The entity vector destroyer.
- * 
+ *
  * This function will free all memory used by all entities, and then empty the
  * vectors they were stored in.
  */
@@ -177,25 +177,25 @@ deleteEntities( void )
                delete npc.back();
                npc.pop_back();
        }
-    
+
     // free structures
        while ( !build.empty() ) {
                delete build.back();
                build.pop_back();
        }
-    
+
     // free objects
        while ( !object.empty() ) {
                delete object.back();
                object.pop_back();
        }
-    
+
     // clear entity array
        entity.clear();
-    
+
     // free particles
        particles.clear();
-    
+
     // clear light array
        light.clear();
 
@@ -208,7 +208,7 @@ deleteEntities( void )
 
 /**
  * The world destructor.
- * 
+ *
  * This will free objects used by the world itself, then free the vectors of
  * entity-related objects.
  */
@@ -219,9 +219,9 @@ World::
     // sdl2_mixer's object
        if(bgmObj)
                Mix_FreeMusic(bgmObj);
-    
+
        delete bgTex;
-       
+
        delete[] toLeft;
        delete[] toRight;
 
@@ -230,20 +230,20 @@ World::
 
 /**
  * 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");
@@ -251,17 +251,17 @@ generate( unsigned int width )
     // 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)
@@ -279,15 +279,15 @@ generate( unsigned int width )
             (*wditer).groundHeight = GROUND_HEIGHT_MINIMUM;
         else if ( (*wditer).groundHeight > GROUND_HEIGHT_MAXIMUM )
                        (*wditer).groundHeight = GROUND_HEIGHT_MAXIMUM;
-               
+
                if( (*wditer).groundHeight <= 0 )
                        (*wditer).groundHeight = GROUND_HEIGHT_MINIMUM;
 
     }
-    
+
     // define x-coordinate of world's leftmost 'line'
     worldStart = (width - GROUND_HILLINESS) * HLINE / 2 * -1;
-       
+
     // create empty star array, should be filled here as well...
        star = std::vector<vec2> (100, vec2 { 0, 400 } );
        for ( auto &s : star ) {
@@ -298,7 +298,7 @@ generate( unsigned int width )
 
 /**
  * Updates all entity and player coordinates with their velocities.
- * 
+ *
  * Also handles music fading, although that could probably be placed elsewhere.
  */
 
@@ -308,15 +308,20 @@ 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;
-       
+
+       if ( p->loc.y > 5000 ) {
+               std::cout << "Too high for me m8." << std::endl;
+               abort();
+       }
+
        // update entity coords
        for ( auto &e : entity ) {
                e->loc.y += e->vel.y * delta;
-               
+
         // dont let structures move?
                if ( e->type != STRUCTURET && e->canMove ) {
                        e->loc.x += e->vel.x * delta;
-                       
+
             // update boolean directions
                        if ( e->vel.x < 0 )
                 e->left = true;
@@ -342,7 +347,7 @@ update( Player *p, unsigned int delta )
                        }
                }
        }
-       
+
     // handle music fades
        if ( ui::dialogImportant )
                Mix_FadeOutMusic(2000);
@@ -352,7 +357,7 @@ update( Player *p, unsigned int delta )
 
 /**
  * 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.
  */
@@ -366,7 +371,7 @@ setBGM( std::string path )
 
 /**
  * Toggle play/stop of the background music.
- * 
+ *
  * If new music is to be played a crossfade will occur, otherwise... uhm.
  */
 
@@ -388,7 +393,7 @@ bgmPlay( World *prev ) const
 
 /**
  * The world draw function.
- * 
+ *
  * This function will draw the background layers, entities, and player to the
  * screen.
  */
@@ -398,34 +403,34 @@ 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 background images.
      */
-       
+
        glEnable( GL_TEXTURE_2D );
-       
+
        // the sunny wallpaper is faded with the night depending on tickCount
-       
+
        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 );
@@ -435,24 +440,24 @@ draw( Player *p )
 
        bgTex->bindNext();
        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 );
-       
+
        // 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 ( worldShade > 0 ) {
 
                safeSetColorA( 255, 255, 255, 255 - (getRand() % 30 - 15) );
-               
+
                for ( i = 0; i < 100; i++ ) {
                        glRectf(star[i].x + offset.x * .9,
                                        star[i].y,
@@ -460,15 +465,15 @@ draw( Player *p )
                                        star[i].y + HLINE
                                        );
                }
-       } 
-       
+       }
+
        // draw remaining background items
-       
+
        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        );
@@ -477,11 +482,11 @@ draw( Player *p )
                        glTexCoord2i( 0, 0 ); glVertex2i( width / 2 * -1 + (1920 * i      ) + offset.x * .85, GROUND_HEIGHT_MINIMUM + 1080 );
                }
        glEnd();
-       
+
        for ( i = 0; i < 4; i++ ) {
                bgTex->bindNext();
                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       );
@@ -491,22 +496,22 @@ draw( Player *p )
                        }
                glEnd();
        }
-       
+
        glDisable( GL_TEXTURE_2D );
-       
+
        // draw black under backgrounds
-       
+
        glColor3ub( 0, 0, 0 );
        glRectf( worldStart, GROUND_HEIGHT_MINIMUM, -worldStart, 0 );
-       
+
        pOffset = (offset.x + p->width / 2 - worldStart) / HLINE;
-       
+
     /*
      * Prepare for world ground drawing.
      */
-    
+
        // only draw world within player vision
-    
+
        if ((iStart = pOffset - (SCREEN_WIDTH / 2 / HLINE) - GROUND_HILLINESS) < 0)
                iStart = 0;
 
@@ -518,51 +523,51 @@ draw( Player *p )
        // draw particles and buildings
 
        std::for_each( particles.begin(), particles.end(), [](Particles part) { if ( part.behind ) part.draw(); });
-       
+
        for ( auto &b : build )
                b->draw();
 
        // draw light elements?
-       
+
        glEnable( GL_TEXTURE_2D );
-    
+
        glActiveTexture( GL_TEXTURE0 );
        bgTex->bindNext();
-       
+
        std::unique_ptr<GLfloat[]> pointArrayBuf = std::make_unique<GLfloat[]> (2 * (light.size() + p->light));
        auto pointArray = pointArrayBuf.get();
-       
+
        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;
        }
-       
+
        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"    ), shadeAmbient );
-       
+
        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 ); 
+               glUniform2fv( glGetUniformLocation( shaderProgram, "lightLocation"), light.size() + (int)p->light, pointArray );
                glUniform3f ( glGetUniformLocation( shaderProgram, "lightColor"   ), 1.0f, 1.0f, 1.0f );
        }
-       
+
     /*
      * 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);
@@ -578,50 +583,50 @@ draw( Player *p )
 
             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;
         }
-       
+
        glEnd();
-    
+
        glUseProgram(0);
        glDisable(GL_TEXTURE_2D);
-       
+
        /*
         *      Draw the grass/the top of the ground.
         */
 
        glEnable( GL_TEXTURE_2D );
-    
+
        glActiveTexture( GL_TEXTURE0 );
        bgTex->bindNext();
-       
+
        glUseProgram( shaderProgram );
        glUniform1i( glGetUniformLocation( shaderProgram, "sampler"), 0);
 
        float cgh[2];
        for ( i = iStart; i < iEnd - GROUND_HILLINESS; i++ ) {
-               
+
                // 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.
-               
+
                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] );
@@ -640,9 +645,9 @@ draw( Player *p )
        /*
      * Draw remaining entities.
      */
-       
+
        std::for_each( particles.begin(), particles.end(), [](Particles part) { if ( !part.behind ) part.draw(); });
-       
+
        for ( auto &n : npc )
                n->draw();
 
@@ -651,11 +656,11 @@ draw( Player *p )
 
        for ( auto &o : object )
                o->draw();
-       
+
     /*
      * Handle grass-squishing.
      */
-    
+
        // calculate the line that the player is on
        int ph = ( p->loc.x + p->width / 2 - worldStart ) / HLINE;
 
@@ -671,13 +676,13 @@ draw( Player *p )
        /*
      * Draw the player.
      */
-     
+
        p->draw();
 }
 
 /**
  * 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.
  */
@@ -688,11 +693,11 @@ singleDetect( Entity *e )
        std::string killed;
        unsigned int i,j;
        int l;
-       
+
        /*
         *      Kill any dead entities.
        */
-       
+
        if ( !e->alive || e->health <= 0 ) {
                for ( i = 0; i < entity.size(); i++) {
                        if ( entity[i] == e ){
@@ -748,71 +753,77 @@ singleDetect( Entity *e )
                std::cout<<"RIP "<<e->name<<"."<<std::endl;
                exit(0);
        }
-       
+
        /*
         *      Handle only living entities.
        */
-    
+
        if(e->alive){
-         
+
                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 - worldStart) / HLINE;
                if(l < 0) l=0;
                i = l;
                if(i > lineCount-1) i=lineCount-1;
-               
+
                /*
                 *      If the entity is under the world/line, pop it back to the surface.
                */
-               
+
                if ( e->loc.y < worldData[i].groundHeight ) {
 
-                       e->loc.y= worldData[i].groundHeight - .001 * deltaTime;
-                       e->ground=true;
-                       e->vel.y=0;
-               
+      if ( worldData[i].groundHeight - e->loc.y > 30 ) {
+        int dir = e->vel.x > 0 ? -1 : 1;
+        e->loc.x += HLINE * 8 * dir;
+        e->loc.y = worldData[i + 8 * dir].groundHeight;
+      } else {
+        e->loc.y = worldData[i].groundHeight - .001 * deltaTime;
+                         e->ground = true;
+                         e->vel.y = 0;
+      }
+
                /*
                 *      Handle gravity if the entity is above the line.
                */
-               
+
                }else{
-                       
+
                        if(e->type == STRUCTURET && e->loc.y > 2000){
                                e->loc.y = worldData[i].groundHeight;
                                e->vel.y = 0;
                                e->ground = true;
                                return;
                        }else if(e->vel.y > -2)e->vel.y-=.003 * deltaTime;
-                                       
+
                }
-               
+
                /*
                 *      Insure that the entity doesn't fall off either edge of the world.
                */
 
                if(e->loc.x < worldStart){                                                                                              // Left bound
-                       
+
                        e->vel.x=0;
                        e->loc.x=(float)worldStart + HLINE / 2;
-                       
+
                }else if(e->loc.x + e->width + HLINE > worldStart + worldStart * -2){   // Right bound
-                       
+
                        e->vel.x=0;
                        e->loc.x=worldStart + worldStart * -2 - e->width - HLINE;
-                       
+
                }
        }
 }
 
 /**
  * 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.
@@ -822,20 +833,20 @@ void World::
 detect( Player *p )
 {
        int l;
-       
+
        // handle the player
        std::thread( &World::singleDetect, this, p).detach();
-               
+
     // handle other entities
        for ( auto &e : entity )
                std::thread(&World::singleDetect,this,e).detach();
-        
+
     // 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;
 
@@ -851,7 +862,7 @@ detect( Player *p )
                } else if ( part.gravity && part.vely > -2 )
                        part.vely -= .003 * deltaTime;
        }
-       
+
        // handle particle creation
        for ( auto &b : build ) {
                switch ( b->bsubtype ) {
@@ -870,7 +881,7 @@ detect( Player *p )
                                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
@@ -909,18 +920,18 @@ 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());
 }
 
 void World::addMob(int t,float x,float y){
        mob.push_back(new Mob(t));
        mob.back()->spawn(x,y);
-       
+
        entity.push_back(mob.back());
 }
 
@@ -928,14 +939,14 @@ void World::addMob(int t,float x,float y,void (*hey)(Mob *)){
        mob.push_back(new Mob(t));
        mob.back()->spawn(x,y);
        mob.back()->hey = hey;
-       
+
        entity.push_back(mob.back());
 }
 
 void World::addNPC(float x,float y){
        npc.push_back(new NPC());
        npc.back()->spawn(x,y);
-       
+
        entity.push_back(npc.back());
 }
 
@@ -975,7 +986,7 @@ char *World::setToLeft(const char *file){
                delete[] toLeft;
        if(!file)
                return (toLeft = NULL);
-       
+
        strcpy((toLeft = new char[strlen(file) + 1]),file);
        return toLeft;
 }
@@ -984,7 +995,7 @@ char *World::setToRight(const char *file){
                delete[] toRight;
        if(!file)
                return (toRight = NULL);
-       
+
        strcpy((toRight = new char[strlen(file) + 1]),file);
        return toRight;
 }
@@ -993,33 +1004,37 @@ World *World::
 goWorldLeft( Player *p )
 {
        World *tmp;
-    
-    // check if player is at world edge
-       if(toLeft && p->loc.x < worldStart + HLINE * 15.0f){
-        
-        // load world (`toLeft` conditional confirms existance)
+
+  // 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);
-               
-        // adjust player location
-               p->loc.x = tmp->worldStart - HLINE * -10.0f;
+
+    // adjust player location
+               p->loc.x = tmp->worldStart + HLINE * 20;
                p->loc.y = tmp->worldData[tmp->lineCount - 1].groundHeight;
-               
+
                return tmp;
        }
+
        return this;
-}              
+}
 
-World *World::goWorldRight(Player *p){
+World *World::
+goWorldRight( Player *p )
+{
        World *tmp;
-       
-       if(toRight && p->loc.x + p->width > -worldStart - HLINE * 15){
+
+       if( toRight && p->loc.x + p->width > -worldStart - HLINE * 15 ) {
                tmp = loadWorldFromXML(toRight);
-               
-               p->loc.x = tmp->worldStart + HLINE * 10;
+
+               p->loc.x = tmp->worldStart - HLINE * -15.0f;
                p->loc.y = GROUND_HEIGHT_MINIMUM;
-               
+
                return tmp;
        }
+
        return this;
 }
 
@@ -1033,13 +1048,13 @@ goInsideStructure( Player *p )
                        if(p->loc.x            > b->loc.x            &&
                           p->loc.x + p->width < b->loc.x + b->width ){
                                inside.push_back((std::string)(currentXML.c_str() + 4));
-                               
+
                                tmp = loadWorldFromXML(b->inside.c_str());
-                               
+
                                ui::toggleBlackFast();
                                ui::waitForCover();
                                ui::toggleBlackFast();
-                               
+
                                return tmp;
                        }
                }
@@ -1052,11 +1067,11 @@ goInsideStructure( Player *p )
 
                                ui::toggleBlackFast();
                                ui::waitForCover();
-                               
+
                                p->loc.x = b->loc.x + (b->width / 2);
-                               
+
                                ui::toggleBlackFast();
-                               
+
                                return tmp;
                        }
                }
@@ -1065,10 +1080,32 @@ goInsideStructure( Player *p )
        return this;
 }
 
-void World::addHole(unsigned int start,unsigned int end){
-       unsigned int i;
-       for(i=start;i<end;i++){
+void World::
+addHole( unsigned int start, unsigned int end )
+{
+       for ( unsigned int i = end; i-- > start; )
                worldData[i].groundHeight = 0;
+}
+
+void World::
+addHill( const ivec2 peak, const unsigned int width )
+{
+       int start = peak.x - width / 2, end = start + width, offset;
+       const float thing = peak.y - worldData[start].groundHeight;
+  const float period = PI / width;
+
+       if ( start < 0 ) {
+    offset = -start;
+               start = 0;
+  }
+
+       if ( end > (signed)worldData.size() )
+         end = worldData.size();
+
+       for ( int i = start; i < end; i++ ) {
+               worldData[i].groundHeight += thing * sin((i - start + offset) * period);
+               if ( worldData[i].groundHeight > peak.y )
+                       worldData[i].groundHeight = peak.y;
        }
 }
 
@@ -1080,10 +1117,10 @@ getTheWidth( void ) const
 
 void World::save(void){
        std::string data;
-       
+
        std::string save = (std::string)currentXML + ".dat";
        std::ofstream out (save,std::ios::out | std::ios::binary);
-       
+
        std::cout<<"Saving to "<<save<<" ..."<<std::endl;
 
        for(auto &n : npc){
@@ -1091,40 +1128,40 @@ void World::save(void){
                data.append(std::to_string((int)n->loc.x) + "\n");
                data.append(std::to_string((int)n->loc.y) + "\n");
        }
-       
+
        for(auto &b : build){
                data.append(std::to_string((int)b->loc.x) + "\n");
                data.append(std::to_string((int)b->loc.y) + "\n");
        }
-       
+
        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("dOnE\0");
        out.write(data.c_str(),data.size());
-       
+
        out.close();
 }
 
 void World::load(void){
        std::string save,data,line;
        const char *filedata;
-       
+
        save = (std::string)currentXML + ".dat";
        filedata = readFile(save.c_str());
        data = filedata;
        std::istringstream iss (data);
-       
+
        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();
-               
+
                std::getline(iss,line);
                if(line == "dOnE")return;
                n->loc.x = std::stoi(line);
@@ -1132,7 +1169,7 @@ void World::load(void){
                if(line == "dOnE")return;
                n->loc.y = std::stoi(line);
        }
-       
+
        for(auto &b : build){
                std::getline(iss,line);
                if(line == "dOnE")return;
@@ -1141,7 +1178,7 @@ void World::load(void){
                if(line == "dOnE")return;
                b->loc.y = std::stoi(line);
        }
-       
+
        for(auto &m : mob){
                std::getline(iss,line);
                if(line == "dOnE")return;
@@ -1153,12 +1190,12 @@ void World::load(void){
                if(line == "dOnE")return;
                m->alive = std::stoi(line);
        }
-       
+
        while(std::getline(iss,line)){
                if(line == "dOnE")
                        break;
        }
-       
+
        delete[] filedata;
 }
 
@@ -1167,16 +1204,16 @@ IndoorWorld::IndoorWorld(void){
 
 IndoorWorld::~IndoorWorld(void){
        delete bgTex;
-       
+
        deleteEntities();
 }
 
 void IndoorWorld::generate(unsigned int width){                // Generates a flat area of width 'width'
        lineCount=width+GROUND_HILLINESS;                       // Sets line count to the desired width plus GEN_INC to remove incorrect line calculations.
        if(lineCount<=0)abort();
-       
+
        worldData = std::vector<WorldData> (lineCount, WorldData { false, {0,0}, INDOOR_FLOOR_HEIGHT, 0 });
-       
+
        worldStart = (width - GROUND_HILLINESS) * HLINE / 2 * -1;
 }
 
@@ -1184,71 +1221,71 @@ void IndoorWorld::draw(Player *p){
        unsigned int i,ie;
        //int j,x,v_offset;
        int x;
-       
+
        /*
         *      Draw the background.
        */
-       
+
        glEnable(GL_TEXTURE_2D);
-       
+
        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;
        }
-       
+
        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 ); 
+               glUniform2fv( glGetUniformLocation( shaderProgram, "lightLocation"), light.size() + (int)p->light, pointArray );
                glUniform3f ( glGetUniformLocation( shaderProgram, "lightColor"   ), 1.0f, 1.0f, 1.0f );
        }
-       
+
        bgTex->bind(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
        glColor4ub(255,255,255,255);
-       
+
        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);
        glDisable(GL_TEXTURE_2D);
-       
+
        /*
         *      Calculate the starting and ending points to draw the ground from.
        */
-       
+
        /*v_offset = (p->loc.x - x_start) / HLINE;
        j = v_offset - (SCREEN_WIDTH / 2 / HLINE) - GEN_INC;
        if(j < 0)j = 0;
        i = j;
-       
+
        ie = v_offset + (SCREEN_WIDTH / 2 / HLINE) - GEN_INC;
        if(ie > lineCount)ie = lineCount;*/
-       
+
        i = 0;
        ie = lineCount;
-       
+
        /*
         *      Draw the ground.
        */
@@ -1257,7 +1294,7 @@ void IndoorWorld::draw(Player *p){
        glBegin(GL_QUADS);
                for(;i < ie - GROUND_HILLINESS;i++){
                        safeSetColor(150,100,50);
-                       
+
                        x = worldStart + i * HLINE;
                        glVertex2i(x            ,worldData[i].groundHeight);
                        glVertex2i(x + HLINE,worldData[i].groundHeight);
@@ -1266,11 +1303,11 @@ void IndoorWorld::draw(Player *p){
                }
        glEnd();
        glUseProgram(0);
-       
+
        /*
         *      Draw all entities.
        */
-       
+
        for ( auto &part : particles )
                part.draw();
 
@@ -1283,14 +1320,14 @@ void IndoorWorld::draw(Player *p){
 Arena::Arena(World *leave,Player *p,Mob *m){
        generate(800);
        addMob(MS_DOOR,100,100);
-       
+
        inBattle = true;
        mmob = m;
        mmob->aggressive = false;
-       
+
        mob.push_back(m);
        entity.push_back(m);
-       
+
        battleNest.push_back(leave);
        battleNestLoc.push_back(p->loc);
 }
@@ -1305,17 +1342,17 @@ World *Arena::exitArena(Player *p){
           p->loc.x + p->width / 2 < mob[0]->loc.x + HLINE * 12 ){
                tmp = battleNest.front();
                battleNest.erase(battleNest.begin());
-               
+
                inBattle = !battleNest.empty();
                ui::toggleBlackFast();
                ui::waitForCover();
-               
+
                p->loc = battleNestLoc.back();
                battleNestLoc.pop_back();
-               
+
                mob.clear();
                mmob->alive = false;
-               
+
                return tmp;
        }else{
                return this;
@@ -1338,14 +1375,14 @@ loadWorldFromXMLNoSave( std::string path ) {
        XMLDocument xml;
        XMLElement *wxml;
        XMLElement *vil;
-       
+
        World *tmp;
        float spawnx, randx;
        bool dialog,Indoor;
-       
+
        const char *ptr;
        std::string name;
-               
+
        currentXML = (std::string)"xml/" + path;
 
        xml.LoadFile(currentXML.c_str());
@@ -1362,10 +1399,10 @@ loadWorldFromXMLNoSave( std::string path ) {
                Indoor = true;
                tmp = new IndoorWorld();
        }
-       
+
        while(wxml){
                name = wxml->Name();
-               
+
                if ( name == "link" ) {
                        if((ptr = wxml->Attribute("left")))
                                tmp->setToLeft(ptr);
@@ -1382,7 +1419,7 @@ loadWorldFromXMLNoSave( std::string path ) {
                                if(Indoor)
                                        ((IndoorWorld *)tmp)->generate(wxml->UnsignedAttribute("width"));
                                else {
-                                       
+
                                        tmp->generate(wxml->UnsignedAttribute("width"));
                                }
                        }else if(Indoor)
@@ -1396,7 +1433,7 @@ loadWorldFromXMLNoSave( std::string path ) {
                                tmp->addMob(type,spawnx,wxml->FloatAttribute("y"));
                        if(wxml->QueryBoolAttribute("aggressive",&dialog) == XML_NO_ERROR)
                                tmp->mob.back()->aggressive = dialog;
-                       
+
                } else if ( name == "npc" ) {
                        const char *npcname;
 
@@ -1404,23 +1441,23 @@ loadWorldFromXMLNoSave( std::string path ) {
                                tmp->addNPC(0,100);
                        else
                                tmp->addNPC(spawnx,wxml->FloatAttribute("y"));
-                       
-                       
+
+
                        if((npcname = wxml->Attribute("name"))){
                                delete[] tmp->npc.back()->name;
                                tmp->npc.back()->name = new char[strlen(npcname) + 1];
                                strcpy(tmp->npc.back()->name,npcname);
                        }
-                       
+
                        dialog = false;
                        if(wxml->QueryBoolAttribute("hasDialog",&dialog) == XML_NO_ERROR && dialog)
                                tmp->npc.back()->addAIFunc(commonAIFunc,false);
                        else tmp->npc.back()->dialogIndex = 9999;
-                       
+
                } else if ( name == "structure" ) {
                        tmp->addStructure((BUILD_SUB)wxml->UnsignedAttribute("type"),
-                                                          wxml->QueryFloatAttribute("x",&spawnx) != XML_NO_ERROR ? 
-                                                                               getRand() % tmp->getTheWidth() / 2.0f : 
+                                                          wxml->QueryFloatAttribute("x",&spawnx) != XML_NO_ERROR ?
+                                                                               getRand() % tmp->getTheWidth() / 2.0f :
                                                                                spawnx,
                                                           100,
                                                           wxml->StrAttribute("texture"),
@@ -1431,7 +1468,11 @@ loadWorldFromXMLNoSave( std::string path ) {
                } else if ( name == "page" ) {
                        tmp->addMob( MS_PAGE, wxml->FloatAttribute("x"), 0, commonPageFunc );
                        tmp->mob.back()->heyid = wxml->Attribute("id");
-               }
+               } else if ( name == "hill" ) {
+                       tmp->addHill( ivec2 { wxml->IntAttribute("peakx"), wxml->IntAttribute("peaky") }, wxml->UnsignedAttribute("width") );
+               } else if ( name == "time") {
+      tickCount = std::stoi( wxml->GetText() );
+    }
 
                wxml = wxml->NextSiblingElement();
        }
@@ -1453,7 +1494,7 @@ loadWorldFromXMLNoSave( std::string path ) {
                /**
                 *      READS DATA ABOUT STRUCTURE CONTAINED IN VILLAGE
                 */
-                
+
                if ( name == "structure" ) {
                        tmp->addStructure((BUILD_SUB)vil->UnsignedAttribute("type"),
                                                           vil->QueryFloatAttribute("x", &spawnx) != XML_NO_ERROR ? randx : spawnx,
@@ -1464,7 +1505,7 @@ loadWorldFromXMLNoSave( std::string path ) {
                        if(!strcmp(vil->Attribute("type"),"market")){
                                std::cout << "Market" << std::endl;
                                tmp->addStructure((BUILD_SUB)70,
-                                                          vil->QueryFloatAttribute("x", &spawnx) != XML_NO_ERROR ? 
+                                                          vil->QueryFloatAttribute("x", &spawnx) != XML_NO_ERROR ?
                                                           randx : spawnx,
                                                           100,
                                                           vil->StrAttribute("texture"),
@@ -1488,20 +1529,20 @@ loadWorldFromXMLNoSave( std::string path ) {
                        }else if(!strcmp(vil->Attribute("type"),"trader")){
                                std::cout << "Trader" << std::endl;
                                tmp->addStructure((BUILD_SUB)71,
-                                                          vil->QueryFloatAttribute("x", &spawnx) != XML_NO_ERROR ? 
+                                                          vil->QueryFloatAttribute("x", &spawnx) != XML_NO_ERROR ?
                                                           randx : spawnx,
                                                           100,
                                                           vil->StrAttribute("texture"),
                                                           vil->StrAttribute("inside"));
                        }
                }
-               
+
                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(vptr->build.back()->loc.x + vptr->build.back()->width > vptr->end.x){
                        vptr->end.x = vptr->build.back()->loc.x + vptr->build.back()->width;
                }
@@ -1509,7 +1550,7 @@ loadWorldFromXMLNoSave( std::string path ) {
                //go to the next element in the village block
                vil = vil->NextSiblingElement();
        }
-       
+
        std::ifstream dat (((std::string)currentXML + ".dat").c_str());
        if(dat.good()){
                dat.close();
index c79b93f9cef67ed240428508a729e33ef3ea462d..86ee3972537ecf42d24ae50cd71540a689d7303a 100644 (file)
@@ -2,17 +2,20 @@
 <World>
        <style background="0" bgm="assets/music/embark.wav" folder="assets/style/classic/" />
        <generation type="Random" width="500" />
-       <link left="playerSpawnHill2.xml" />
-       
-       <mob x="300" type="1" aggressive="true" />
-       
-       <trigger x="-300" id="Test" />
-       
+       <link right="playerSpawnHill2.xml" />
+       <time>12000</time>
+
+       <hill peakx="0" peaky="1000" width="50" />
+
+       <mob x="300" type="1" aggressive="false" />
+
+       <!--<trigger x="-300" id="Test" />-->
+
        <npc name="Ralph" hasDialog="true" />
        <npc name="Johnny" hasDialog="false" />
-       
+
        <page x="-200" id="assets/pages/gootaGoFast.png" />
-       
+
        <village name="the Cranmore Tubing Park">
                <structure type="0" x="-300" inside="playerSpawnHill1_Building1.xml"/>
                <structure type="5" x="-500" inside="playerSpawnHill1_Building1.xml"/>
@@ -32,20 +35,20 @@ And it wasn't stormy.
 ...</Trigger>
 
 <Dialog name="Ralph">
-       
+
        <text id="0" nextid="1" >
                Hello there! My name is Ralph.
        </text>
-       
+
        <text id="1" nextid="2" call="Johnny" callid="0" pause="true" >
                You should go talk to my friend Johnny. He's a pretty chill dude.
        </text>
-       
+
        <text id="2" >
                Niice.
                <quest check="Your First Quest" fail="3" />
        </text>
-       
+
        <text id="3">
                Go check out Johnny. He's cool.
        </text>
@@ -59,7 +62,7 @@ And it wasn't stormy.
                        Wood Sword,1
                </quest>
        </text>
-       
+
        <text id="1" nextid="1" pause="true" >
                Broooooooooooooo...
        </text>
index 67695c73c4ac63afcf9b77dd5e003ebf6bdfa198..f0c8a21ab2b4ae11468f830f44567dbb064d0da1 100644 (file)
@@ -2,7 +2,7 @@
 <IndoorWorld>
        <style background="1" bgm="assets/music/theme_jazz.wav" />
        <generation type="Random" width="300" />
-       
+
        <npc name="Bob" hasDialog="true" />
 
 </IndoorWorld>
                Hey. Have a Dank MayMay :)
                <give id="Dank MayMay" count="1" />
        </text>
-       
+
        <text id="1" nextid="2">
                What? You want another Dank MayMay?
        </text>
-       
+
        <text id="2" nextid="3" pause="true">
                K.
                <give id="Dank MayMay" count="1" />
        </text>
-       
+
        <text id="3" nextid="4">
                Well... I'm out of Dank MayMays.
        </text>
-       
+
        <text id="4">
                Have a sword though.
                <give id="Wood Sword" count="1" />
        </text>
-       
+
 </Dialog>
index c46dad33c34365d0adef4fb0aba20d6c137f4107..8d3d328551af0b7d740e2bb0c19898ed5fbc7741 100644 (file)
@@ -3,7 +3,7 @@
        <style background="0" bgm="assets/music/embark.wav" folder="assets/style/rustic/"/>
        <generation type="Random" width="1000" />
        <structure type="5" inside="playerSpawnHill1_Building1.xml"/>
-       
-       <link right="playerSpawnHill1.xml" />
+
+       <link left="playerSpawnHill1.xml" />
 
 </World>