]> git.jsancho.org Git - lugaru.git/blobdiff - Source/Environment/Terrain.cpp
Fixed a few parentheses
[lugaru.git] / Source / Environment / Terrain.cpp
index 164dce38fd6a02739d221c4e5282204584d6283a..6d195e204eaf9f5c39262b07c01b8a2d3f006af2 100644 (file)
@@ -21,8 +21,9 @@ along with Lugaru.  If not, see <http://www.gnu.org/licenses/>.
 #include "Environment/Terrain.hpp"
 
 #include "Game.hpp"
-#include "Objects/Objects.hpp"
+#include "Objects/Object.hpp"
 #include "Utils/Folders.hpp"
+#include "Tutorial.hpp"
 
 extern XYZ viewer;
 extern float viewdistance;
@@ -34,13 +35,10 @@ extern float multiplier;
 extern FRUSTUM frustum;
 extern float texdetail;
 extern int detail;
-extern bool decals;
+extern bool decalstoggle;
 extern float blurness;
 extern float targetblurness;
-extern Objects objects;
-extern bool visibleloading;
 extern bool skyboxtexture;
-extern int tutoriallevel;
 
 //Functions
 
@@ -427,8 +425,7 @@ bool Terrain::load(const std::string& fileName)
         }
     }
     texture.bpp = 24;
-    if (visibleloading)
-        Game::LoadingScreen();
+    Game::LoadingScreen();
 
     texdetail = temptexdetail;
 
@@ -440,8 +437,7 @@ bool Terrain::load(const std::string& fileName)
         }
     }
 
-    if (visibleloading)
-        Game::LoadingScreen();
+    Game::LoadingScreen();
 
     float slopeness;
 
@@ -450,8 +446,7 @@ bool Terrain::load(const std::string& fileName)
             textureness[i][j] = -1;
         }
     }
-    if (visibleloading)
-        Game::LoadingScreen();
+    Game::LoadingScreen();
 
 
     for (i = 0; i < size; i++) {
@@ -500,8 +495,7 @@ bool Terrain::load(const std::string& fileName)
             }
         }
     }
-    if (visibleloading)
-        Game::LoadingScreen();
+    Game::LoadingScreen();
 
     for (i = 0; i < size; i++) {
         for (j = 0; j < size; j++) {
@@ -513,8 +507,7 @@ bool Terrain::load(const std::string& fileName)
             }
         }
     }
-    if (visibleloading)
-        Game::LoadingScreen();
+    Game::LoadingScreen();
 
     for (i = 0; i < size; i++) {
         for (j = 0; j < size; j++) {
@@ -639,11 +632,10 @@ bool Terrain::load(const std::string& fileName)
             }
         }
     }
-    if (visibleloading)
-        Game::LoadingScreen();
+    Game::LoadingScreen();
 
     patch_size = size / subdivision;
-    patch_elements = (patch_size) * (patch_size) * 54;
+    patch_elements = patch_size * patch_size * 54;
     CalculateNormals();
 
     return true;
@@ -733,7 +725,9 @@ void Terrain::drawpatch(int whichx, int whichy, float opacity)
         glEnable(GL_BLEND);
         UpdateTransparency(whichx, whichy);
     }
+
     glColor4f(1, 1, 1, 1);
+
     //Set up vertex array
     glEnableClientState(GL_VERTEX_ARRAY);
     glEnableClientState(GL_COLOR_ARRAY);
@@ -757,7 +751,9 @@ void Terrain::drawpatchother(int whichx, int whichy, float opacity)
         UpdateTransparency(whichx, whichy);
     }
     UpdateTransparencyother(whichx, whichy);
+
     glColor4f(1, 1, 1, 1);
+
     //Set up vertex array
     glEnableClientState(GL_VERTEX_ARRAY);
     glEnableClientState(GL_COLOR_ARRAY);
@@ -774,7 +770,7 @@ void Terrain::drawpatchother(int whichx, int whichy, float opacity)
     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 }
 
-void Terrain::drawpatchotherother(int whichx, int whichy, float opacity)
+void Terrain::drawpatchotherother(int whichx, int whichy)
 {
     glEnable(GL_BLEND);
     UpdateTransparencyotherother(whichx, whichy);
@@ -936,17 +932,17 @@ void Terrain::draw(int layer)
     viewdistsquared = viewdistance * viewdistance;
 
     //Only nearby blocks
-    beginx = (viewer.x - viewdistance) / (patch_size) - 1;
+    beginx = ((viewer.x - viewdistance) / patch_size) - 1;
     if (beginx < 0)
         beginx = 0;
-    beginz = (viewer.z - viewdistance) / (patch_size) - 1;
+    beginz = ((viewer.z - viewdistance) / patch_size) - 1;
     if (beginz < 0)
         beginz = 0;
 
-    endx = (viewer.x + viewdistance) / (patch_size) + 1;
+    endx = ((viewer.x + viewdistance) / patch_size) + 1;
     if (endx > subdivision)
         endx = subdivision;
-    endz = (viewer.z + viewdistance) / (patch_size) + 1;
+    endz = ((viewer.z + viewdistance) / patch_size) + 1;
     if (endz > subdivision)
         endz = subdivision;
 
@@ -987,7 +983,7 @@ void Terrain::draw(int layer)
                     if (layer == 1 && textureness[i][j] != allfirst)
                         drawpatchother(i, j, opacity);
                     if (layer == 2 && textureness[i][j] != allfirst)
-                        drawpatchotherother(i, j, opacity);
+                        drawpatchotherother(i, j);
                 }
                 glPopMatrix();
             }
@@ -999,8 +995,7 @@ void Terrain::draw(int layer)
 
 void Terrain::drawdecals()
 {
-    if (decals) {
-        static int i;
+    if (decalstoggle) {
         static float distancemult;
         static int lasttype;
 
@@ -1016,87 +1011,89 @@ void Terrain::drawdecals()
         glDisable(GL_CULL_FACE);
         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
         glDepthMask(0);
-        for (i = 0; i < numdecals; i++) {
-            if (decaltype[i] == blooddecalfast && decalalivetime[i] < 2)
-                decalalivetime[i] = 2;
-            if ((decaltype[i] == shadowdecal || decaltype[i] == shadowdecalpermanent) && decaltype[i] != lasttype) {
-                shadowtexture.bind();
-                if (!blend) {
-                    blend = 1;
-                    glAlphaFunc(GL_GREATER, 0.0001);
-                    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+        for (unsigned int i = 0; i < decals.size(); i++) {
+            if (decals[i].type == blooddecalfast && decals[i].alivetime < 2)
+                decals[i].alivetime = 2;
+            if (decals[i].type != lasttype) {
+                if (decals[i].type == shadowdecal || decals[i].type == shadowdecalpermanent) {
+                    shadowtexture.bind();
+                    if (!blend) {
+                        blend = 1;
+                        glAlphaFunc(GL_GREATER, 0.0001);
+                        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+                    }
                 }
-            }
-            if (decaltype[i] == footprintdecal && decaltype[i] != lasttype) {
-                footprinttexture.bind();
-                if (!blend) {
-                    blend = 1;
-                    glAlphaFunc(GL_GREATER, 0.0001);
-                    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+                if (decals[i].type == footprintdecal) {
+                    footprinttexture.bind();
+                    if (!blend) {
+                        blend = 1;
+                        glAlphaFunc(GL_GREATER, 0.0001);
+                        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+                    }
                 }
-            }
-            if (decaltype[i] == bodyprintdecal && decaltype[i] != lasttype) {
-                bodyprinttexture.bind();
-                if (!blend) {
-                    blend = 1;
-                    glAlphaFunc(GL_GREATER, 0.0001);
-                    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+                if (decals[i].type == bodyprintdecal) {
+                    bodyprinttexture.bind();
+                    if (!blend) {
+                        blend = 1;
+                        glAlphaFunc(GL_GREATER, 0.0001);
+                        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+                    }
                 }
-            }
-            if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalslow) && decaltype[i] != lasttype) {
-                bloodtexture.bind();
-                if (blend) {
-                    blend = 0;
-                    glAlphaFunc(GL_GREATER, 0.15);
-                    glBlendFunc(GL_ONE, GL_ZERO);
+                if (decals[i].type == blooddecal || decals[i].type == blooddecalslow) {
+                    bloodtexture.bind();
+                    if (blend) {
+                        blend = 0;
+                        glAlphaFunc(GL_GREATER, 0.15);
+                        glBlendFunc(GL_ONE, GL_ZERO);
+                    }
                 }
-            }
-            if ((decaltype[i] == blooddecalfast) && decaltype[i] != lasttype) {
-                bloodtexture2.bind();
-                if (blend) {
-                    blend = 0;
-                    glAlphaFunc(GL_GREATER, 0.15);
-                    glBlendFunc(GL_ONE, GL_ZERO);
+                if (decals[i].type == blooddecalfast) {
+                    bloodtexture2.bind();
+                    if (blend) {
+                        blend = 0;
+                        glAlphaFunc(GL_GREATER, 0.15);
+                        glBlendFunc(GL_ONE, GL_ZERO);
+                    }
                 }
             }
-            if (decaltype[i] == shadowdecal || decaltype[i] == shadowdecalpermanent) {
-                distancemult = (viewdistsquared - (distsq(&viewer, &decalposition[i]) - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
+            if (decals[i].type == shadowdecal || decals[i].type == shadowdecalpermanent) {
+                distancemult = (viewdistsquared - (distsq(&viewer, &decals[i].position) - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
                 if (distancemult >= 1)
-                    glColor4f(1, 1, 1, decalopacity[i]);
+                    glColor4f(1, 1, 1, decals[i].opacity);
                 if (distancemult < 1)
-                    glColor4f(1, 1, 1, decalopacity[i]*distancemult);
+                    glColor4f(1, 1, 1, decals[i].opacity*distancemult);
             }
-            if (decaltype[i] == footprintdecal || decaltype[i] == bodyprintdecal) {
-                distancemult = (viewdistsquared - (distsq(&viewer, &decalposition[i]) - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
+            if (decals[i].type == footprintdecal || decals[i].type == bodyprintdecal) {
+                distancemult = (viewdistsquared - (distsq(&viewer, &decals[i].position) - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
                 if (distancemult >= 1) {
-                    glColor4f(1, 1, 1, decalopacity[i]);
-                    if (decalalivetime[i] > 3)
-                        glColor4f(1, 1, 1, decalopacity[i] * (5 - decalalivetime[i]) / 2);
+                    glColor4f(1, 1, 1, decals[i].opacity);
+                    if (decals[i].alivetime > 3)
+                        glColor4f(1, 1, 1, decals[i].opacity * (5 - decals[i].alivetime) / 2);
                 }
                 if (distancemult < 1) {
-                    glColor4f(1, 1, 1, decalopacity[i]*distancemult);
-                    if (decalalivetime[i] > 3)
-                        glColor4f(1, 1, 1, decalopacity[i] * (5 - decalalivetime[i]) / 2 * distancemult);
+                    glColor4f(1, 1, 1, decals[i].opacity*distancemult);
+                    if (decals[i].alivetime > 3)
+                        glColor4f(1, 1, 1, decals[i].opacity * (5 - decals[i].alivetime) / 2 * distancemult);
                 }
             }
-            if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalfast || decaltype[i] == blooddecalslow)) {
-                distancemult = (viewdistsquared - (distsq(&viewer, &decalposition[i]) - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
+            if ((decals[i].type == blooddecal || decals[i].type == blooddecalfast || decals[i].type == blooddecalslow)) {
+                distancemult = (viewdistsquared - (distsq(&viewer, &decals[i].position) - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
                 if (distancemult >= 1) {
-                    glColor4f(decalbrightness[i], decalbrightness[i], decalbrightness[i], decalopacity[i]);
-                    if (decalalivetime[i] < 4)
-                        glColor4f(decalbrightness[i], decalbrightness[i], decalbrightness[i], decalopacity[i]*decalalivetime[i]*.25);
-                    if (decalalivetime[i] > 58)
-                        glColor4f(decalbrightness[i], decalbrightness[i], decalbrightness[i], decalopacity[i] * (60 - decalalivetime[i]) / 2);
+                    glColor4f(decals[i].brightness, decals[i].brightness, decals[i].brightness, decals[i].opacity);
+                    if (decals[i].alivetime < 4)
+                        glColor4f(decals[i].brightness, decals[i].brightness, decals[i].brightness, decals[i].opacity*decals[i].alivetime*.25);
+                    if (decals[i].alivetime > 58)
+                        glColor4f(decals[i].brightness, decals[i].brightness, decals[i].brightness, decals[i].opacity * (60 - decals[i].alivetime) / 2);
                 }
                 if (distancemult < 1) {
-                    glColor4f(decalbrightness[i], decalbrightness[i], decalbrightness[i], decalopacity[i]*distancemult);
-                    if (decalalivetime[i] < 4)
-                        glColor4f(decalbrightness[i], decalbrightness[i], decalbrightness[i], decalopacity[i]*decalalivetime[i]*distancemult * .25);
-                    if (decalalivetime[i] > 58)
-                        glColor4f(decalbrightness[i], decalbrightness[i], decalbrightness[i], decalopacity[i] * (60 - decalalivetime[i]) / 2 * distancemult);
+                    glColor4f(decals[i].brightness, decals[i].brightness, decals[i].brightness, decals[i].opacity*distancemult);
+                    if (decals[i].alivetime < 4)
+                        glColor4f(decals[i].brightness, decals[i].brightness, decals[i].brightness, decals[i].opacity*decals[i].alivetime*distancemult * .25);
+                    if (decals[i].alivetime > 58)
+                        glColor4f(decals[i].brightness, decals[i].brightness, decals[i].brightness, decals[i].opacity * (60 - decals[i].alivetime) / 2 * distancemult);
                 }
             }
-            lasttype = decaltype[i];
+            lasttype = decals[i].type;
             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
 
@@ -1104,95 +1101,78 @@ void Terrain::drawdecals()
             glPushMatrix();
             glBegin(GL_TRIANGLES);
             for (int j = 0; j < 3; j++) {
-                glTexCoord2f(decaltexcoords[i][j][0], decaltexcoords[i][j][1]);
-                glVertex3f(decalvertex[i][j].x, decalvertex[i][j].y, decalvertex[i][j].z);
+                glTexCoord2f(decals[i].texcoords[j][0], decals[i].texcoords[j][1]);
+                glVertex3f(decals[i].vertex[j].x, decals[i].vertex[j].y, decals[i].vertex[j].z);
             }
             glEnd();
             glPopMatrix();
         }
-        for (i = numdecals - 1; i >= 0; i--) {
-            decalalivetime[i] += multiplier;
-            if (decaltype[i] == blooddecalslow)
-                decalalivetime[i] -= multiplier * 2 / 3;
-            if (decaltype[i] == blooddecalfast)
-                decalalivetime[i] += multiplier * 4;
-            if (decaltype[i] == shadowdecal)
+        for (int i = decals.size() - 1; i >= 0; i--) {
+            decals[i].alivetime += multiplier;
+            if (decals[i].type == blooddecalslow)
+                decals[i].alivetime -= multiplier * 2 / 3;
+            if (decals[i].type == blooddecalfast)
+                decals[i].alivetime += multiplier * 4;
+            if (decals[i].type == shadowdecal)
                 DeleteDecal(i);
-            if (decaltype[i] == footprintdecal && decalalivetime[i] >= 5)
+            if (decals[i].type == footprintdecal && decals[i].alivetime >= 5)
                 DeleteDecal(i);
-            if (decaltype[i] == bodyprintdecal && decalalivetime[i] >= 5)
+            if (decals[i].type == bodyprintdecal && decals[i].alivetime >= 5)
                 DeleteDecal(i);
-            if ((decaltype[i] == blooddecal || decaltype[i] == blooddecalfast || decaltype[i] == blooddecalslow) && decalalivetime[i] >= 60)
+            if ((decals[i].type == blooddecal || decals[i].type == blooddecalfast || decals[i].type == blooddecalslow) && decals[i].alivetime >= 60)
                 DeleteDecal(i);
         }
         glAlphaFunc(GL_GREATER, 0.0001);
     }
 }
 
+void Terrain::deleteDeadDecals()
+{
+    for (int i = decals.size() - 1; i >= 0; i--) {
+        if ((decals[i].type == blooddecal || decals[i].type == blooddecalslow) && decals[i].alivetime < 2) {
+            DeleteDecal(i);
+        }
+    }
+}
+
 void Terrain::AddObject(XYZ where, float radius, int id)
 {
-    bool done;
-    int i, j;
-    XYZ points[4];
-    if (id >= 0 && id < 10000)
-        for (i = 0; i < subdivision; i++) {
-            for (j = 0; j < subdivision; j++) {
-                if (patchobjectnum[i][j] < 300 - 1) {
-                    done = 0;
+    XYZ points[2];
+    if (id >= 0 && id < 10000) {
+        for (int i = 0; i < subdivision; i++) {
+            for (int j = 0; j < subdivision; j++) {
+                if (patchobjects[i][j].size() < 300 - 1) {
                     points[0].x = (size / subdivision) * i;
                     points[0].z = (size / subdivision) * j;
                     points[0].y = heightmap[(int)points[0].x][(int)points[0].z];
                     points[1].x = (size / subdivision) * (i + 1);
-                    points[1].z = (size / subdivision) * j;
+                    points[1].z = (size / subdivision) * (j + 1);
                     points[1].y = heightmap[(int)points[1].x][(int)points[1].z];
-                    points[2].x = (size / subdivision) * (i + 1);
-                    points[2].z = (size / subdivision) * (j + 1);
-                    points[2].y = heightmap[(int)points[2].x][(int)points[2].z];
-                    points[3].x = (size / subdivision) * i;
-                    points[3].z = (size / subdivision) * (j + 1);
-                    points[3].y = heightmap[(int)points[3].x][(int)points[3].z];
                     points[0] *= scale;
                     points[1] *= scale;
-                    points[2] *= scale;
-                    points[3] *= scale;
-                    if (!done && where.x + radius > points[0].x && where.x - radius < points[2].x && where.z + radius > points[0].z && where.z - radius < points[2].z) {
-                        patchobjects[i][j][patchobjectnum[i][j]] = id;
-                        patchobjectnum[i][j]++;
-                        done = 1;
+                    if (where.x + radius > points[0].x && where.x - radius < points[1].x && where.z + radius > points[0].z && where.z - radius < points[1].z) {
+                        patchobjects[i][j].push_back(id);
                     }
                 }
             }
         }
+    }
 }
 
 void Terrain::DeleteDecal(int which)
 {
-    if (decals) {
-        decaltype[which] = decaltype[numdecals - 1];
-        decalposition[which] = decalposition[numdecals - 1];
-        for (int i = 0; i < 3; i++) {
-            decalvertex[which][i] = decalvertex[numdecals - 1][i];
-            decaltexcoords[which][i][0] = decaltexcoords[numdecals - 1][i][0];
-            decaltexcoords[which][i][1] = decaltexcoords[numdecals - 1][i][1];
-        }
-        decalrotation[which] = decalrotation[numdecals - 1];
-        decalalivetime[which] = decalalivetime[numdecals - 1];
-        decalopacity[which] = decalopacity[numdecals - 1];
-        decalbrightness[which] = decalbrightness[numdecals - 1];
-        numdecals--;
+    if (decalstoggle) {
+        decals.erase(decals.begin() + which);
     }
 }
 
-void Terrain::MakeDecal(int type, XYZ where, float size, float opacity, float rotation)
+void Terrain::MakeDecal(decal_type type, XYZ where, float size, float opacity, float rotation)
 {
-    if (decals) {
+    if (decalstoggle) {
         if (opacity > 0 && size > 0) {
             static int patchx[4];
             static int patchy[4];
 
-            decaltexcoords[numdecals][0][0] = 1;
-            decaltexcoords[numdecals][0][1] = 0;
-
             patchx[0] = (where.x + size) / scale;
             patchx[1] = (where.x - size) / scale;
             patchx[2] = (where.x - size) / scale;
@@ -1214,160 +1194,58 @@ void Terrain::MakeDecal(int type, XYZ where, float size, float opacity, float ro
             if ((patchx[2] != patchx[3] || patchy[2] != patchy[3])) {
                 MakeDecalLock(type, where, patchx[2], patchy[2], size, opacity, rotation);
             }
+
             MakeDecalLock(type, where, patchx[3], patchy[3], size, opacity, rotation);
         }
     }
-    //}
 }
 
-void Terrain::MakeDecalLock(int type, XYZ where, int whichx, int whichy, float size, float opacity, float rotation)
+void Terrain::MakeDecalLock(decal_type type, XYZ where, int whichx, int whichy, float size, float opacity, float rotation)
 {
-    if (decals) {
-        static float placex, placez;
-        static XYZ rot;
+    if (decalstoggle) {
+        XYZ rot = getLighting(where.x, where.z);
+        float decalbright = (rot.x + rot.y + rot.z) / 3;
 
-        float decalbright;
-
-        rot = getLighting(where.x, where.z);
-        decalbrightness[numdecals] = (rot.x + rot.y + rot.z) / 3;
-        if (decalbrightness[numdecals] < .4)
-            decalbrightness[numdecals] = .4;
+        if (decalbright < .4)
+            decalbright = .4;
 
         if (environment == grassyenvironment) {
-            decalbrightness[numdecals] *= .6;
+            decalbright *= .6;
         }
 
-        if (decalbrightness[numdecals] > 1)
-            decalbrightness[numdecals] = 1;
-        decalbright = decalbrightness[numdecals];
-
-        decalposition[numdecals] = where;
-        decaltype[numdecals] = type;
-        decalopacity[numdecals] = opacity;
-        decalrotation[numdecals] = rotation;
-        decalalivetime[numdecals] = 0;
-
-        placex = (float)whichx * scale + scale;
-        placez = (float)whichy * scale;
-
-        decaltexcoords[numdecals][0][0] = (placex - where.x) / size / 2 + .5;
-        decaltexcoords[numdecals][0][1] = (placez - where.z) / size / 2 + .5;
-
-        decalvertex[numdecals][0].x = placex;
-        decalvertex[numdecals][0].z = placez;
-        decalvertex[numdecals][0].y = heightmap[whichx + 1][whichy] * scale + .01;
-
-
-        placex = (float)whichx * scale + scale;
-        placez = (float)whichy * scale + scale;
-
-        decaltexcoords[numdecals][1][0] = (placex - where.x) / size / 2 + .5;
-        decaltexcoords[numdecals][1][1] = (placez - where.z) / size / 2 + .5;
-
-        decalvertex[numdecals][1].x = placex;
-        decalvertex[numdecals][1].z = placez;
-        decalvertex[numdecals][1].y = heightmap[whichx + 1][whichy + 1] * scale + .01;
-
-
-        placex = (float)whichx * scale;
-        placez = (float)whichy * scale + scale;
-
-        decaltexcoords[numdecals][2][0] = (placex - where.x) / size / 2 + .5;
-        decaltexcoords[numdecals][2][1] = (placez - where.z) / size / 2 + .5;
-
-        decalvertex[numdecals][2].x = placex;
-        decalvertex[numdecals][2].z = placez;
-        decalvertex[numdecals][2].y = heightmap[whichx][whichy + 1] * scale + .01;
-
-        if (decalrotation[numdecals]) {
-            for (int i = 0; i < 3; i++) {
-                rot.y = 0;
-                rot.x = decaltexcoords[numdecals][i][0] - .5;
-                rot.z = decaltexcoords[numdecals][i][1] - .5;
-                rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
-                decaltexcoords[numdecals][i][0] = rot.x + .5;
-                decaltexcoords[numdecals][i][1] = rot.z + .5;
-            }
+        if (decalbright > 1) {
+            decalbright = 1;
         }
 
-        if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
-            if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
-                if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
-                    if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1))
-                        if (numdecals < max_decals - 1)
-                            numdecals++;
-
-        decalbrightness[numdecals] = decalbright;
-
-        decalposition[numdecals] = where;
-        decaltype[numdecals] = type;
-        decalopacity[numdecals] = opacity;
-        decalrotation[numdecals] = rotation;
-        decalalivetime[numdecals] = 0;
-
-        placex = (float)whichx * scale + scale;
-        placez = (float)whichy * scale;
-
-        decaltexcoords[numdecals][0][0] = (placex - where.x) / size / 2 + .5;
-        decaltexcoords[numdecals][0][1] = (placez - where.z) / size / 2 + .5;
-
-        decalvertex[numdecals][0].x = placex;
-        decalvertex[numdecals][0].z = placez;
-        decalvertex[numdecals][0].y = heightmap[whichx + 1][whichy] * scale + .01;
-
-
-        placex = (float)whichx * scale;
-        placez = (float)whichy * scale;
-
-        decaltexcoords[numdecals][1][0] = (placex - where.x) / size / 2 + .5;
-        decaltexcoords[numdecals][1][1] = (placez - where.z) / size / 2 + .5;
-
-        decalvertex[numdecals][1].x = placex;
-        decalvertex[numdecals][1].z = placez;
-        decalvertex[numdecals][1].y = heightmap[whichx][whichy] * scale + .01;
-
+        Decal decal(where, type, opacity, rotation, decalbright, whichx, whichy, size, *this, true);
 
-        placex = (float)whichx * scale;
-        placez = (float)whichy * scale + scale;
+        if (!(decal.texcoords[0][0] < 0 && decal.texcoords[1][0] < 0 && decal.texcoords[2][0] < 0))
+            if (!(decal.texcoords[0][1] < 0 && decal.texcoords[1][1] < 0 && decal.texcoords[2][1] < 0))
+                if (!(decal.texcoords[0][0] > 1 && decal.texcoords[1][0] > 1 && decal.texcoords[2][0] > 1))
+                    if (!(decal.texcoords[0][1] > 1 && decal.texcoords[1][1] > 1 && decal.texcoords[2][1] > 1))
+                        if (decals.size() < max_decals - 1)
+                            decals.push_back(decal);
 
-        decaltexcoords[numdecals][2][0] = (placex - where.x) / size / 2 + .5;
-        decaltexcoords[numdecals][2][1] = (placez - where.z) / size / 2 + .5;
+        Decal decal2(where, type, opacity, rotation, decalbright, whichx, whichy, size, *this, false);
 
-        decalvertex[numdecals][2].x = placex;
-        decalvertex[numdecals][2].z = placez;
-        decalvertex[numdecals][2].y = heightmap[whichx][whichy + 1] * scale + .01;
-
-        if (decalrotation[numdecals]) {
-            for (int i = 0; i < 3; i++) {
-                rot.y = 0;
-                rot.x = decaltexcoords[numdecals][i][0] - .5;
-                rot.z = decaltexcoords[numdecals][i][1] - .5;
-                rot = DoRotation(rot, 0, -decalrotation[numdecals], 0);
-                decaltexcoords[numdecals][i][0] = rot.x + .5;
-                decaltexcoords[numdecals][i][1] = rot.z + .5;
-            }
-        }
-
-        if (!(decaltexcoords[numdecals][0][0] < 0 && decaltexcoords[numdecals][1][0] < 0 && decaltexcoords[numdecals][2][0] < 0))
-            if (!(decaltexcoords[numdecals][0][1] < 0 && decaltexcoords[numdecals][1][1] < 0 && decaltexcoords[numdecals][2][1] < 0))
-                if (!(decaltexcoords[numdecals][0][0] > 1 && decaltexcoords[numdecals][1][0] > 1 && decaltexcoords[numdecals][2][0] > 1))
-                    if (!(decaltexcoords[numdecals][0][1] > 1 && decaltexcoords[numdecals][1][1] > 1 && decaltexcoords[numdecals][2][1] > 1))
-                        if (numdecals < max_decals - 1)
-                            numdecals++;
+        if (!(decal2.texcoords[0][0] < 0 && decal2.texcoords[1][0] < 0 && decal2.texcoords[2][0] < 0))
+            if (!(decal2.texcoords[0][1] < 0 && decal2.texcoords[1][1] < 0 && decal2.texcoords[2][1] < 0))
+                if (!(decal2.texcoords[0][0] > 1 && decal2.texcoords[1][0] > 1 && decal2.texcoords[2][0] > 1))
+                    if (!(decal2.texcoords[0][1] > 1 && decal2.texcoords[1][1] > 1 && decal2.texcoords[2][1] > 1))
+                        if (decals.size() < max_decals - 1)
+                            decals.push_back(decal2);
     }
 }
 
 void Terrain::DoShadows()
 {
-    static int i, j, k, l, todivide;
-    static float brightness, total;
     static XYZ testpoint, testpoint2, terrainpoint, lightloc, col;
     lightloc = light.location;
     if (!skyboxtexture) {
         lightloc.x = 0;
         lightloc.z = 0;
     }
-    if (skyboxtexture && tutoriallevel) {
+    if (skyboxtexture && Tutorial::active) {
         lightloc.x *= .4;
         lightloc.z *= .4;
     }
@@ -1375,30 +1253,29 @@ void Terrain::DoShadows()
     float shadowed;
     Normalise(&lightloc);
     //Calculate shadows
-    for (i = 0; i < size; i++) {
-        for (j = 0; j < size; j++) {
-            terrainpoint.x = (float)(i) * scale;
-            terrainpoint.z = (float)(j) * scale;
+    for (short int i = 0; i < size; i++) {
+        for (short int j = 0; j < size; j++) {
+            terrainpoint.x = (float)i * scale;
+            terrainpoint.z = (float)j * scale;
             terrainpoint.y = heightmap[i][j] * scale;
 
             shadowed = 0;
-            patchx = (float)(i) * subdivision / size;
-            patchz = (float)(j) * subdivision / size;
-            if (patchobjectnum[patchx][patchz]) {
-                for (k = 0; k < patchobjectnum[patchx][patchz]; k++) {
-                    l = patchobjects[patchx][patchz][k];
-                    if (objects.type[l] != treetrunktype) {
+            patchx = (float)i * subdivision / size;
+            patchz = (float)j * subdivision / size;
+            if (patchobjects[patchx][patchz].size()) {
+                for (unsigned int k = 0; k < patchobjects[patchx][patchz].size(); k++) {
+                    unsigned int l = patchobjects[patchx][patchz][k];
+                    if (Object::objects[l]->type != treetrunktype) {
                         testpoint = terrainpoint;
                         testpoint2 = terrainpoint + lightloc * 50 * (1 - shadowed);
-                        if (objects.model[l].LineCheck(&testpoint, &testpoint2, &col, &objects.position[l], &objects.yaw[l]) != -1) {
+                        if (Object::objects[l]->model.LineCheck(&testpoint, &testpoint2, &col, &Object::objects[l]->position, &Object::objects[l]->yaw) != -1) {
                             shadowed = 1 - (findDistance(&terrainpoint, &col) / 50);
                         }
                     }
                 }
-                if (visibleloading)
-                    Game::LoadingScreen();
+                Game::LoadingScreen();
             }
-            brightness = dotproduct(&lightloc, &normals[i][j]);
+            float brightness = dotproduct(&lightloc, &normals[i][j]);
             if (shadowed)
                 brightness *= 1 - shadowed;
 
@@ -1420,15 +1297,14 @@ void Terrain::DoShadows()
         }
     }
 
-    if (visibleloading)
-        Game::LoadingScreen();
+    Game::LoadingScreen();
 
     //Smooth shadows
-    for (i = 0; i < size; i++) {
-        for (j = 0; j < size; j++) {
-            for (k = 0; k < 3; k++) {
-                total = 0;
-                todivide = 0;
+    for (short int i = 0; i < size; i++) {
+        for (short int j = 0; j < size; j++) {
+            for (short int k = 0; k < 3; k++) {
+                float total = 0;
+                unsigned int todivide = 0;
                 if (i != 0) {
                     total += colors[j][i - 1][k];
                     todivide++;
@@ -1469,8 +1345,8 @@ void Terrain::DoShadows()
         }
     }
 
-    for (i = 0; i < subdivision; i++) {
-        for (j = 0; j < subdivision; j++) {
+    for (unsigned int i = 0; i < subdivision; i++) {
+        for (unsigned int j = 0; j < subdivision; j++) {
             UpdateVertexArray(i, j);
         }
     }
@@ -1480,9 +1356,6 @@ Terrain::Terrain()
 {
     size = 0;
 
-    memset(patchobjectnum, 0, sizeof(patchobjectnum));
-    memset(patchobjects, 0, sizeof(patchobjects));
-
     scale = 1.0f;
     type = 0;
     memset(heightmap, 0, sizeof(heightmap));
@@ -1505,25 +1378,4 @@ Terrain::Terrain()
     memset(heightypatch, 0, sizeof(heightypatch));
 
     patch_elements = 0;
-
-    memset(decaltexcoords, 0, sizeof(decaltexcoords));
-    memset(decalvertex, 0, sizeof(decalvertex));
-    memset(decaltype, 0, sizeof(decaltype));
-    memset(decalopacity, 0, sizeof(decalopacity));
-    memset(decalrotation, 0, sizeof(decalrotation));
-    memset(decalalivetime, 0, sizeof(decalalivetime));
-    memset(decalbrightness, 0, sizeof(decalbrightness));
-    memset(decalposition, 0, sizeof(decalposition));
-    numdecals = 0;
 }
-Terrain::~Terrain()
-{
-    terraintexture.destroy();
-    shadowtexture.destroy();
-    bodyprinttexture.destroy();
-    footprinttexture.destroy();
-    bloodtexture.destroy();
-    bloodtexture2.destroy();
-    breaktexture.destroy();
-}
-