]> git.jsancho.org Git - lugaru.git/blobdiff - Source/GameTick.cpp
Moved Account::active in Account class. Maybe it should be changed for a method and...
[lugaru.git] / Source / GameTick.cpp
index 90786725e4e6c489dcf197fbb1d87a41a9e02bd7..fab80e9e5ac4c29b7c07fc9422e0e27236ae2d80 100644 (file)
@@ -38,12 +38,14 @@ along with Lugaru.  If not, see <http://www.gnu.org/licenses/>.
 #include "openal_wrapper.h"
 #include "Settings.h"
 #include "Input.h"
-#include "Animation.h"
+#include "Animation/Animation.h"
 #include "Awards.h"
 #include "Menu.h"
 #include "ConsoleCmds.h"
 #include "Dialog.h"
 #include "Utils/Folders.h"
+#include "Hotspot.h"
+#include "Campaign.h"
 
 #include <algorithm>
 #include <set>
@@ -88,8 +90,8 @@ extern bool mousejump;
 extern float viewdistance;
 extern bool freeze;
 extern XYZ windvector;
-extern bool debugmode;
-static int leveltheme;
+extern bool devtools;
+int leveltheme;
 extern int mainmenu;
 extern int oldmainmenu;
 extern bool visibleloading;
@@ -130,14 +132,6 @@ extern float hostiletime;
 
 extern bool gamestarted;
 
-extern int numhotspots;
-extern int killhotspot;
-extern XYZ hotspot[40];
-extern int hotspottype[40];
-extern float hotspotsize[40];
-extern char hotspottext[40][256];
-extern int currenthotspot;
-
 extern int hostile;
 
 extern bool stillloading;
@@ -147,87 +141,8 @@ extern bool campaign;
 
 extern void toggleFullscreen();
 
-class CampaignLevel
-{
-private:
-    int width;
-    struct Position {
-        int x, y;
-    };
-public:
-    std::string mapname;
-    std::string description;
-    int choosenext;
-    /*
-    0 = Immediately load next level at the end of this one.
-    1 = Go back to the world map.
-    2 = Don't bring up the Fiery loading screen. Maybe other things, I've not investigated.
-    */
-    //int numnext; // 0 on final level. As David said: he meant to add story branching, but he eventually hadn't.
-    std::vector<int> nextlevel;
-    Position location;
-    CampaignLevel() : width(10) {
-        choosenext = 1;
-        location.x = 0;
-        location.y = 0;
-    }
-    int getStartX() {
-        return 30 + 120 + location.x * 400 / 512;
-    }
-    int getStartY() {
-        return 30 + 30 + (512 - location.y) * 400 / 512;
-    }
-    int getEndX() {
-        return getStartX() + width;
-    }
-    int getEndY() {
-        return getStartY() + width;
-    }
-    XYZ getCenter() {
-        XYZ center;
-        center.x = getStartX() + width / 2;
-        center.y = getStartY() + width / 2;
-        return center;
-    }
-    int getWidth() {
-        return width;
-    }
-    istream& operator<< (istream& is) {
-        is.ignore(256, ':');
-        is.ignore(256, ':');
-        is.ignore(256, ' ');
-        is >> mapname;
-        is.ignore(256, ':');
-        is >> description;
-        for (size_t pos = description.find('_'); pos != string::npos; pos = description.find('_', pos)) {
-            description.replace(pos, 1, 1, ' ');
-        }
-        is.ignore(256, ':');
-        is >> choosenext;
-        is.ignore(256, ':');
-        int numnext, next;
-        is >> numnext;
-        for (int j = 0; j < numnext; j++) {
-            is.ignore(256, ':');
-            is >> next;
-            nextlevel.push_back(next - 1);
-        }
-        is.ignore(256, ':');
-        is >> location.x;
-        is.ignore(256, ':');
-        is >> location.y;
-        return is;
-    }
-    friend istream& operator>> (istream& is, CampaignLevel& cl) {
-        return cl << is;
-    }
-};
-
 bool won = false;
-int entername = 0;
-vector<CampaignLevel> campaignlevels;
 int whichchoice = 0;
-int actuallevel = 0;
 bool winhotspot = false;
 bool windialogue = false;
 bool realthreat = 0;
@@ -706,66 +621,6 @@ void Setenvironment(int which)
     texdetail = temptexdetail;
 }
 
-void LoadCampaign()
-{
-    if (!accountactive)
-        return;
-    ifstream ipstream(Folders::getResourcePath("Campaigns/" + accountactive->getCurrentCampaign() + ".txt"));
-    if (!ipstream.good()) {
-        if (accountactive->getCurrentCampaign() == "main") {
-            cerr << "Could not found main campaign!" << endl;
-            return;
-        }
-        cerr << "Could not found campaign \"" << accountactive->getCurrentCampaign() << "\", falling back to main." << endl;
-        accountactive->setCurrentCampaign("main");
-        return LoadCampaign();
-    }
-    ipstream.ignore(256, ':');
-    int numlevels;
-    ipstream >> numlevels;
-    campaignlevels.clear();
-    for (int i = 0; i < numlevels; i++) {
-        CampaignLevel cl;
-        ipstream >> cl;
-        campaignlevels.push_back(cl);
-    }
-    ipstream.close();
-
-    ifstream test(Folders::getResourcePath("Textures/" + accountactive->getCurrentCampaign() + "/World.png"));
-    if (test.good()) {
-        Mainmenuitems[7].load("Textures/" + accountactive->getCurrentCampaign() + "/World.png", 0);
-    } else {
-        Mainmenuitems[7].load("Textures/World.png", 0);
-    }
-
-    if (accountactive->getCampaignChoicesMade() == 0) {
-        accountactive->setCampaignScore(0);
-        accountactive->resetFasttime();
-    }
-}
-
-vector<string> ListCampaigns()
-{
-    errno = 0;
-    DIR *campaigns = opendir(Folders::getResourcePath("Campaigns").c_str());
-    struct dirent *campaign = NULL;
-    if (!campaigns) {
-        perror(("Problem while loading campaigns from " + Folders::getResourcePath("Campaigns")).c_str());
-        exit(EXIT_FAILURE);
-    }
-    vector<string> campaignNames;
-    while ((campaign = readdir(campaigns)) != NULL) {
-        string name(campaign->d_name);
-        if (name.length() < 5)
-            continue;
-        if (!name.compare(name.length() - 4, 4, ".txt")) {
-            campaignNames.push_back(name.substr(0, name.length() - 4));
-        }
-    }
-    closedir(campaigns);
-    return campaignNames;
-}
-
 void Game::Loadlevel(int which)
 {
     stealthloading = 0;
@@ -827,7 +682,7 @@ void Game::Loadlevel(const std::string& name)
     hostiletime = 0;
     won = 0;
 
-    animation[bounceidleanim].Load((char *)"Idle", middleheight, neutral);
+    //~ Animation::animations[bounceidleanim].Load("Idle", middleheight, neutral);
 
     Dialog::dialogs.clear();
 
@@ -837,11 +692,11 @@ void Game::Loadlevel(const std::string& name)
     damagedealt = 0;
     damagetaken = 0;
 
-    if (accountactive)
-        difficulty = accountactive->getDifficulty();
+    if (Account::active)
+        difficulty = Account::active->getDifficulty();
 
-    numhotspots = 0;
-    currenthotspot = -1;
+    Hotspot::hotspots.clear();
+    Hotspot::current = -1;
     bonustime = 1;
 
     skyboxtexture = 1;
@@ -906,6 +761,9 @@ void Game::Loadlevel(const std::string& name)
     Person::players.resize(1);
 
     funpackf(tfile, "Bi", &mapvers);
+    if (mapvers < 12) {
+        cerr << name << " has obsolete map version " << mapvers << endl;
+    }
     if (mapvers >= 15)
         funpackf(tfile, "Bi", &indemo);
     else
@@ -939,10 +797,12 @@ void Game::Loadlevel(const std::string& name)
         skyboxlightg = skyboxg;
         skyboxlightb = skyboxb;
     }
-    if (!stealthloading)
-        funpackf(tfile, "Bf Bf Bf Bf Bf Bi", &Person::players[0]->coords.x, &Person::players[0]->coords.y, &Person::players[0]->coords.z, &Person::players[0]->yaw, &Person::players[0]->targetyaw, &Person::players[0]->num_weapons);
-    if (stealthloading)
+    /* TODO - This should be done in an other way so that we can rebuild main player as well (so coords would need to be copied from old ones after rebuilding) */
+    if (stealthloading) {
         funpackf(tfile, "Bf Bf Bf Bf Bf Bi", &lamefloat, &lamefloat, &lamefloat, &lamefloat, &lamefloat, &Person::players[0]->num_weapons);
+    } else {
+        funpackf(tfile, "Bf Bf Bf Bf Bf Bi", &Person::players[0]->coords.x, &Person::players[0]->coords.y, &Person::players[0]->coords.z, &Person::players[0]->yaw, &Person::players[0]->targetyaw, &Person::players[0]->num_weapons);
+    }
     if (Person::players[0]->num_weapons > 0 && Person::players[0]->num_weapons < 5)
         for (int j = 0; j < Person::players[0]->num_weapons; j++) {
             Person::players[0]->weaponids[j] = weapons.size();
@@ -995,19 +855,26 @@ void Game::Loadlevel(const std::string& name)
     }
 
     if (mapvers >= 7) {
+        int numhotspots;
         funpackf(tfile, "Bi", &numhotspots);
-        for (int i = 0; i < numhotspots; i++) {
-            funpackf(tfile, "Bi Bf Bf Bf Bf", &hotspottype[i], &hotspotsize[i], &hotspot[i].x, &hotspot[i].y, &hotspot[i].z);
+        if (numhotspots < 0) {
+            cerr << "Map " << name << " have an invalid number of hotspots" << endl;
+            numhotspots = 0;
+        }
+        Hotspot::hotspots.resize(numhotspots);
+        for (int i = 0; i < Hotspot::hotspots.size(); i++) {
+            funpackf(tfile, "Bi Bf Bf Bf Bf", &Hotspot::hotspots[i].type, &Hotspot::hotspots[i].size, &Hotspot::hotspots[i].position.x, &Hotspot::hotspots[i].position.y, &Hotspot::hotspots[i].position.z);
             funpackf(tfile, "Bi", &templength);
             if (templength)
                 for (int l = 0; l < templength; l++)
-                    funpackf(tfile, "Bb", &hotspottext[i][l]);
-            hotspottext[i][templength] = '\0';
-            if (hotspottype[i] == -111)
+                    funpackf(tfile, "Bb", &Hotspot::hotspots[i].text[l]);
+            Hotspot::hotspots[i].text[templength] = '\0';
+            if (Hotspot::hotspots[i].type == -111)
                 indemo = 1;
         }
-    } else
-        numhotspots = 0;
+    } else {
+        Hotspot::hotspots.clear();
+    }
 
     if (visibleloading)
         LoadingScreen();
@@ -1041,12 +908,13 @@ void Game::Loadlevel(const std::string& name)
     if (numplayers > maxplayers) {
         cout << "Warning: this level contains more players than allowed" << endl;
     }
+    unsigned j = 1;
     for (int i = 1; i < numplayers; i++) {
-        unsigned j = 1;
         try {
             Person::players.push_back(shared_ptr<Person>(new Person(tfile, mapvers, j)));
             j++;
         } catch (InvalidPersonException e) {
+            cerr << "Invalid Person found in " << name << endl;
         }
     }
     if (visibleloading)
@@ -1093,92 +961,63 @@ void Game::Loadlevel(const std::string& name)
     for (unsigned i = 0; i < Person::players.size(); i++) {
         if (visibleloading)
             LoadingScreen();
-        Person::players[i]->burnt = 0;
-        Person::players[i]->bled = 0;
-        Person::players[i]->onfire = 0;
-        if (i == 0 || Person::players[i]->scale < 0)
+        if (i == 0) {
+            Person::players[i]->burnt = 0;
+            Person::players[i]->bled = 0;
+            Person::players[i]->onfire = 0;
             Person::players[i]->scale = .2;
-        Person::players[i]->skeleton.free = 0;
-        Person::players[i]->skeleton.id = i;
-        if (i == 0 && mapvers < 9)
-            Person::players[i]->creature = rabbittype;
-        if (Person::players[i]->creature != wolftype) {
-            Person::players[i]->skeleton.Load(
-                (char *)"Skeleton/BasicFigure",
-                (char *)"Skeleton/BasicFigureLow",
-                (char *)"Skeleton/RabbitBelt",
-                (char *)"Models/Body.solid",
-                (char *)"Models/Body2.solid",
-                (char *)"Models/Body3.solid",
-                (char *)"Models/Body4.solid",
-                (char *)"Models/Body5.solid",
-                (char *)"Models/Body6.solid",
-                (char *)"Models/Body7.solid",
-                (char *)"Models/BodyLow.solid",
-                (char *)"Models/Belt.solid", 0);
-        } else {
-            Person::players[i]->skeleton.Load(
-                (char *)"Skeleton/BasicFigureWolf",
-                (char *)"Skeleton/BasicFigureWolfLow",
-                (char *)"Skeleton/RabbitBelt",
-                (char *)"Models/Wolf.solid",
-                (char *)"Models/Wolf2.solid",
-                (char *)"Models/Wolf3.solid",
-                (char *)"Models/Wolf4.solid",
-                (char *)"Models/Wolf5.solid",
-                (char *)"Models/Wolf6.solid",
-                (char *)"Models/Wolf7.solid",
-                (char *)"Models/WolfLow.solid",
-                (char *)"Models/Belt.solid", 0);
+            if (mapvers < 9) {
+                Person::players[i]->creature = rabbittype;
+            }
         }
+        Person::players[i]->skeleton.free = 0;
 
-        Person::players[i]->skeleton.drawmodel.textureptr.load(creatureskin[Person::players[i]->creature][Person::players[i]->whichskin], 1, &Person::players[i]->skeleton.skinText[0], &Person::players[i]->skeleton.skinsize);
+        Person::players[i]->skeletonLoad();
 
         Person::players[i]->addClothes();
 
-        Person::players[i]->animCurrent = bounceidleanim;
-        Person::players[i]->animTarget = bounceidleanim;
-        Person::players[i]->frameCurrent = 0;
-        Person::players[i]->frameTarget = 1;
-        Person::players[i]->target = 0;
+        if (i == 0) {
+            Person::players[i]->animCurrent = bounceidleanim;
+            Person::players[i]->animTarget = bounceidleanim;
+            Person::players[i]->frameCurrent = 0;
+            Person::players[i]->frameTarget = 1;
+            Person::players[i]->target = 0;
+        }
         Person::players[i]->speed = 1 + (float)(Random() % 100) / 1000;
         if (difficulty == 0)
             Person::players[i]->speed -= .2;
         if (difficulty == 1)
             Person::players[i]->speed -= .1;
 
-        Person::players[i]->velocity = 0;
-        Person::players[i]->oldcoords = Person::players[i]->coords;
-        Person::players[i]->realoldcoords = Person::players[i]->coords;
-
-        Person::players[i]->id = i;
-        Person::players[i]->skeleton.id = i;
-        Person::players[i]->updatedelay = 0;
-        Person::players[i]->normalsupdatedelay = 0;
+        if (i == 0) {
+            Person::players[i]->velocity = 0;
+            Person::players[i]->oldcoords = Person::players[i]->coords;
+            Person::players[i]->realoldcoords = Person::players[i]->coords;
 
-        Person::players[i]->aitype = passivetype;
+            Person::players[i]->id = i;
+            Person::players[i]->updatedelay = 0;
+            Person::players[i]->normalsupdatedelay = 0;
 
-        if (i == 0) {
             Person::players[i]->proportionhead = 1.2;
             Person::players[i]->proportionbody = 1.05;
             Person::players[i]->proportionarms = 1.00;
             Person::players[i]->proportionlegs = 1.1;
             Person::players[i]->proportionlegs.y = 1.05;
-        }
-        Person::players[i]->headless = 0;
-        Person::players[i]->currentoffset = 0;
-        Person::players[i]->targetoffset = 0;
-
-        Person::players[i]->damagetolerance = 200;
-
-        if (Person::players[i]->creature == wolftype) {
-            if (i == 0 || Person::players[i]->scale < 0)
+            Person::players[i]->headless = 0;
+            Person::players[i]->currentoffset = 0;
+            Person::players[i]->targetoffset = 0;
+            if (Person::players[i]->creature == wolftype) {
                 Person::players[i]->scale = .23;
-            Person::players[i]->damagetolerance = 300;
+                Person::players[i]->damagetolerance = 300;
+            } else {
+                Person::players[i]->damagetolerance = 200;
+            }
         }
 
+
         if (visibleloading)
             LoadingScreen();
+
         if (cellophane) {
             Person::players[i]->proportionhead.z = 0;
             Person::players[i]->proportionbody.z = 0;
@@ -1186,43 +1025,44 @@ void Game::Loadlevel(const std::string& name)
             Person::players[i]->proportionlegs.z = 0;
         }
 
-        Person::players[i]->tempanimation.Load((char *)"Tempanim", 0, 0);
-
-        Person::players[i]->headmorphness = 0;
-        Person::players[i]->targetheadmorphness = 1;
-        Person::players[i]->headmorphstart = 0;
-        Person::players[i]->headmorphend = 0;
-
-        Person::players[i]->pausetime = 0;
-
-        Person::players[i]->dead = 0;
-        Person::players[i]->jumppower = 5;
-        Person::players[i]->damage = 0;
-        Person::players[i]->permanentdamage = 0;
-        Person::players[i]->superpermanentdamage = 0;
-
-        Person::players[i]->forwardkeydown = 0;
-        Person::players[i]->leftkeydown = 0;
-        Person::players[i]->backkeydown = 0;
-        Person::players[i]->rightkeydown = 0;
-        Person::players[i]->jumpkeydown = 0;
-        Person::players[i]->crouchkeydown = 0;
-        Person::players[i]->throwkeydown = 0;
-
-        Person::players[i]->collided = -10;
-        Person::players[i]->loaded = 1;
-        Person::players[i]->bloodloss = 0;
-        Person::players[i]->weaponactive = -1;
-        Person::players[i]->weaponstuck = -1;
-        Person::players[i]->bleeding = 0;
-        Person::players[i]->deathbleeding = 0;
-        Person::players[i]->stunned = 0;
-        Person::players[i]->hasvictim = 0;
-        Person::players[i]->wentforweapon = 0;
+        Person::players[i]->tempanimation = Animation("Tempanim", lowheight, neutral);
+
+        if (i == 0) {
+            Person::players[i]->headmorphness = 0;
+            Person::players[i]->targetheadmorphness = 1;
+            Person::players[i]->headmorphstart = 0;
+            Person::players[i]->headmorphend = 0;
+
+            Person::players[i]->pausetime = 0;
+
+            Person::players[i]->dead = 0;
+            Person::players[i]->jumppower = 5;
+            Person::players[i]->damage = 0;
+            Person::players[i]->permanentdamage = 0;
+            Person::players[i]->superpermanentdamage = 0;
+
+            Person::players[i]->forwardkeydown = 0;
+            Person::players[i]->leftkeydown = 0;
+            Person::players[i]->backkeydown = 0;
+            Person::players[i]->rightkeydown = 0;
+            Person::players[i]->jumpkeydown = 0;
+            Person::players[i]->crouchkeydown = 0;
+            Person::players[i]->throwkeydown = 0;
+
+            Person::players[i]->collided = -10;
+            Person::players[i]->loaded = 1;
+            Person::players[i]->bloodloss = 0;
+            Person::players[i]->weaponactive = -1;
+            Person::players[i]->weaponstuck = -1;
+            Person::players[i]->bleeding = 0;
+            Person::players[i]->deathbleeding = 0;
+            Person::players[i]->stunned = 0;
+            Person::players[i]->hasvictim = 0;
+            Person::players[i]->wentforweapon = 0;
+        }
     }
 
     Person::players[0]->aitype = playercontrolled;
-    Person::players[0]->weaponactive = -1;
 
     if (difficulty == 1) {
         Person::players[0]->power = 1 / .9;
@@ -1266,6 +1106,7 @@ void Game::Loadlevel(const std::string& name)
         firstload = 1;
 
     leveltime = 0;
+    wonleveltime = 0;
     visibleloading = 0;
 }
 
@@ -1335,7 +1176,7 @@ void doTutorial()
 
             emit_sound_at(fireendsound, Person::players[1]->coords);
 
-            for (int i = 0; i < Person::players[1]->skeleton.num_joints; i++) {
+            for (int i = 0; i < Person::players[1]->skeleton.joints.size(); i++) {
                 if (Random() % 2 == 0) {
                     if (!Person::players[1]->skeleton.free)
                         temp2 = (Person::players[1]->coords - Person::players[1]->oldcoords) / multiplier / 2; //velocity/2;
@@ -1605,7 +1446,7 @@ void doTutorial()
             XYZ temp, temp2;
             emit_sound_at(fireendsound, Person::players[1]->coords);
 
-            for (int i = 0; i < Person::players[1]->skeleton.num_joints; i++) {
+            for (int i = 0; i < Person::players[1]->skeleton.joints.size(); i++) {
                 if (Random() % 2 == 0) {
                     if (!Person::players[1]->skeleton.free)
                         temp2 = (Person::players[1]->coords - Person::players[1]->oldcoords) / multiplier / 2; //velocity/2;
@@ -1720,7 +1561,7 @@ void doTutorial()
                 tutorialsuccess = 1;
             break;
         case 28:
-            if (animation[Person::players[0]->animTarget].attack == reversed && Person::players[0]->feint)
+            if (Animation::animations[Person::players[0]->animTarget].attack == reversed && Person::players[0]->feint)
                 tutorialsuccess = 1;
             break;
         case 29:
@@ -1732,15 +1573,15 @@ void doTutorial()
             }
             break;
         case 33:
-            if (animation[Person::players[0]->animTarget].attack == reversal)
+            if (Animation::animations[Person::players[0]->animTarget].attack == reversal)
                 tutorialsuccess = 1;
             break;
         case 34:
-            if (animation[Person::players[0]->animTarget].attack == reversal)
+            if (Animation::animations[Person::players[0]->animTarget].attack == reversal)
                 tutorialsuccess = 1;
             break;
         case 35:
-            if (animation[Person::players[0]->animTarget].attack == reversal) {
+            if (Animation::animations[Person::players[0]->animTarget].attack == reversal) {
                 tutorialsuccess = 1;
                 reversaltrain = 0;
                 cananger = 0;
@@ -1760,15 +1601,15 @@ void doTutorial()
                 tutorialsuccess = 1;
             break;
         case 44:
-            if (animation[Person::players[0]->animTarget].attack == reversal)
+            if (Animation::animations[Person::players[0]->animTarget].attack == reversal)
                 tutorialsuccess = 1;
             break;
         case 45:
-            if (animation[Person::players[0]->animTarget].attack == reversal)
+            if (Animation::animations[Person::players[0]->animTarget].attack == reversal)
                 tutorialsuccess = 1;
             break;
         case 46:
-            if (animation[Person::players[0]->animTarget].attack == reversal)
+            if (Animation::animations[Person::players[0]->animTarget].attack == reversal)
                 tutorialsuccess = 1;
             break;
         case 49:
@@ -1798,10 +1639,15 @@ void doTutorial()
     }
 }
 
-void doDebugKeys()
+void doDevKeys()
 {
     float headprop, bodyprop, armprop, legprop;
-    if (debugmode) {
+    if (!devtools) {
+        return;
+    }
+
+    if (Input::isKeyDown(SDL_SCANCODE_LALT)) {
+        /* Invicible */
         if (Input::isKeyPressed(SDL_SCANCODE_H)) {
             Person::players[0]->damagetolerance = 200000;
             Person::players[0]->damage = 0;
@@ -1810,6 +1656,7 @@ void doDebugKeys()
             Person::players[0]->superpermanentdamage = 0;
         }
 
+        /* Change environment */
         if (Input::isKeyPressed(SDL_SCANCODE_J)) {
             environment++;
             if (environment > 2)
@@ -1817,33 +1664,49 @@ void doDebugKeys()
             Setenvironment(environment);
         }
 
+        /* Camera mode */
         if (Input::isKeyPressed(SDL_SCANCODE_C)) {
             cameramode = !cameramode;
         }
 
-        if (Input::isKeyPressed(SDL_SCANCODE_X) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
-            if (Person::players[0]->num_weapons > 0) {
-                if (weapons[Person::players[0]->weaponids[0]].getType() == sword)
-                    weapons[Person::players[0]->weaponids[0]].setType(staff);
-                else if (weapons[Person::players[0]->weaponids[0]].getType() == staff)
-                    weapons[Person::players[0]->weaponids[0]].setType(knife);
-                else
-                    weapons[Person::players[0]->weaponids[0]].setType(sword);
+        /* Toggle Slow motion */
+        if (Input::isKeyPressed(SDL_SCANCODE_B)) {
+            slomo = 1 - slomo;
+            slomodelay = 1000;
+        }
+
+        /* Ragdoll */
+        if (Input::isKeyPressed(SDL_SCANCODE_N)) {
+            Person::players[0]->RagDoll(0);
+
+            emit_sound_at(whooshsound, Person::players[0]->coords, 128.);
+        }
+
+        /* Grow tree leaves?? */
+        if (Input::isKeyPressed(SDL_SCANCODE_Y)) {
+            for (int i = 0; i < objects.numobjects; i++) {
+                if (objects.type[i] == treeleavestype) {
+                    objects.scale[i] *= .9;
+                }
             }
         }
 
-        if (Input::isKeyPressed(SDL_SCANCODE_X) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
-            int closest = findClosestPlayer();
+        /* Change (or add) weapon */
+        if (Input::isKeyPressed(SDL_SCANCODE_X)) {
+            int closest = 0;
+            if (!Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
+                closest = findClosestPlayer();
+            }
+
             if (closest >= 0) {
-                if (Person::players[closest]->num_weapons) {
+                if (Person::players[closest]->num_weapons > 0) {
                     if (weapons[Person::players[closest]->weaponids[0]].getType() == sword)
                         weapons[Person::players[closest]->weaponids[0]].setType(staff);
                     else if (weapons[Person::players[closest]->weaponids[0]].getType() == staff)
                         weapons[Person::players[closest]->weaponids[0]].setType(knife);
                     else
                         weapons[Person::players[closest]->weaponids[0]].setType(sword);
-                }
-                if (!Person::players[closest]->num_weapons) {
+                } else {
                     Person::players[closest]->weaponids[0] = weapons.size();
 
                     weapons.push_back(Weapon(knife, closest));
@@ -1853,19 +1716,37 @@ void doDebugKeys()
             }
         }
 
+        /* Change yaw? */
         if (Input::isKeyDown(SDL_SCANCODE_U)) {
-            int closest = findClosestPlayer();
+            int closest = 0;
+            if (!Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
+                closest = findClosestPlayer();
+            }
+
             if (closest >= 0) {
                 Person::players[closest]->yaw += multiplier * 50;
                 Person::players[closest]->targetyaw = Person::players[closest]->yaw;
             }
         }
 
+        /* Toggle fire */
+        if (Input::isKeyPressed(SDL_SCANCODE_F)) {
+            Person::players[0]->onfire = 1 - Person::players[0]->onfire;
+            if (Person::players[0]->onfire) {
+                Person::players[0]->CatchFire();
+            }
+            if (!Person::players[0]->onfire) {
+                emit_sound_at(fireendsound, Person::players[0]->coords);
+                pause_sound(stream_firesound);
+            }
+        }
 
+        /* Change skin */
         if (Input::isKeyPressed(SDL_SCANCODE_O) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
-            int closest = findClosestPlayer();
-            if (Input::isKeyDown(SDL_SCANCODE_LCTRL))
-                closest = 0;
+            int closest = 0;
+            if (!Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
+                closest = findClosestPlayer();
+            }
 
             if (closest >= 0) {
                 Person::players[closest]->whichskin++;
@@ -1881,8 +1762,13 @@ void doDebugKeys()
             Person::players[closest]->addClothes();
         }
 
+        /* Change creature type */
         if (Input::isKeyPressed(SDL_SCANCODE_O) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
-            int closest = findClosestPlayer();
+            int closest = 0;
+            if (!Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
+                closest = findClosestPlayer();
+            }
+
             if (closest >= 0) {
                 if (Person::players[closest]->creature == wolftype) {
                     headprop = Person::players[closest]->proportionhead.x / 1.1;
@@ -1900,11 +1786,9 @@ void doDebugKeys()
 
 
                 if (Person::players[closest]->creature == rabbittype) {
-                    Person::players[closest]->skeleton.id = closest;
-                    Person::players[closest]->skeleton.Load((char *)"Skeleton/BasicFigureWolf", (char *)"Skeleton/BasicFigureWolfLow", (char *)"Skeleton/RabbitBelt", (char *)"Models/Wolf.solid", (char *)"Models/Wolf2.solid", (char *)"Models/Wolf3.solid", (char *)"Models/Wolf4.solid", (char *)"Models/Wolf5.solid", (char *)"Models/Wolf6.solid", (char *)"Models/Wolf7.solid", (char *)"Models/WolfLow.solid", (char *)"Models/Belt.solid", 0);
-                    Person::players[closest]->skeleton.drawmodel.textureptr.load("Textures/Wolf.jpg", 1, &Person::players[closest]->skeleton.skinText[0], &Person::players[closest]->skeleton.skinsize);
-                    Person::players[closest]->whichskin = 0;
                     Person::players[closest]->creature = wolftype;
+                    Person::players[closest]->whichskin = 0;
+                    Person::players[closest]->skeletonLoad();
 
                     Person::players[closest]->proportionhead = 1.1;
                     Person::players[closest]->proportionbody = 1.1;
@@ -1915,11 +1799,9 @@ void doDebugKeys()
 
                     Person::players[closest]->damagetolerance = 300;
                 } else {
-                    Person::players[closest]->skeleton.id = closest;
-                    Person::players[closest]->skeleton.Load((char *)"Skeleton/BasicFigure", (char *)"Skeleton/BasicFigureLow", (char *)"Skeleton/RabbitBelt", (char *)"Models/Body.solid", (char *)"Models/Body2.solid", (char *)"Models/Body3.solid", (char *)"Models/Body4.solid", (char *)"Models/Body5.solid", (char *)"Models/Body6.solid", (char *)"Models/Body7.solid", (char *)"Models/BodyLow.solid", (char *)"Models/Belt.solid", 1);
-                    Person::players[closest]->skeleton.drawmodel.textureptr.load("Textures/Fur3.jpg", 1, &Person::players[closest]->skeleton.skinText[0], &Person::players[closest]->skeleton.skinsize);
-                    Person::players[closest]->whichskin = 0;
                     Person::players[closest]->creature = rabbittype;
+                    Person::players[closest]->whichskin = 0;
+                    Person::players[closest]->skeletonLoad(true);
 
                     Person::players[closest]->proportionhead = 1.2;
                     Person::players[closest]->proportionbody = 1.05;
@@ -1949,12 +1831,7 @@ void doDebugKeys()
             }
         }
 
-        if (Input::isKeyPressed(SDL_SCANCODE_B) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
-            slomo = 1 - slomo;
-            slomodelay = 1000;
-        }
-
-
+        /* Decapitate */
         if (((Input::isKeyPressed(SDL_SCANCODE_I) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT)))) {
             int closest = -1;
             float closestdist = std::numeric_limits<float>::max();
@@ -1975,7 +1852,7 @@ void doDebugKeys()
                 XYZ headspurtdirection;
                 //int i = Person::players[closest]->skeleton.jointlabels[head];
                 Joint& headjoint = Person::players[closest]->joint(head);
-                for (int k = 0; k < Person::players[closest]->skeleton.num_joints; k++) {
+                for (int k = 0; k < Person::players[closest]->skeleton.joints.size(); k++) {
                     if (!Person::players[closest]->skeleton.free)
                         flatvelocity2 = Person::players[closest]->velocity;
                     if (Person::players[closest]->skeleton.free)
@@ -2009,6 +1886,7 @@ void doDebugKeys()
             }
         }
 
+        /* Explode */
         if (((Input::isKeyPressed(SDL_SCANCODE_I) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)))) {
             int closest = findClosestPlayer();
             XYZ flatfacing2, flatvelocity2;
@@ -2018,7 +1896,7 @@ void doDebugKeys()
                 emit_sound_at(splattersound, blah);
                 emit_sound_at(breaksound2, blah);
 
-                for (int i = 0; i < Person::players[closest]->skeleton.num_joints; i++) {
+                for (int i = 0; i < Person::players[closest]->skeleton.joints.size(); i++) {
                     if (!Person::players[closest]->skeleton.free)
                         flatvelocity2 = Person::players[closest]->velocity;
                     if (Person::players[closest]->skeleton.free)
@@ -2035,7 +1913,7 @@ void doDebugKeys()
                     Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
                 }
 
-                for (int i = 0; i < Person::players[closest]->skeleton.num_joints; i++) {
+                for (int i = 0; i < Person::players[closest]->skeleton.joints.size(); i++) {
                     if (!Person::players[closest]->skeleton.free)
                         flatvelocity2 = Person::players[closest]->velocity;
                     if (Person::players[closest]->skeleton.free)
@@ -2051,7 +1929,7 @@ void doDebugKeys()
                     Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
                 }
 
-                for (int i = 0; i < Person::players[closest]->skeleton.num_joints; i++) {
+                for (int i = 0; i < Person::players[closest]->skeleton.joints.size(); i++) {
                     if (!Person::players[closest]->skeleton.free)
                         flatvelocity2 = Person::players[closest]->velocity;
                     if (Person::players[closest]->skeleton.free)
@@ -2067,7 +1945,7 @@ void doDebugKeys()
                     Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2 * 2, 1, 1, 1, .4, 1);
                 }
 
-                for (int i = 0; i < Person::players[closest]->skeleton.num_joints; i++) {
+                for (int i = 0; i < Person::players[closest]->skeleton.joints.size(); i++) {
                     if (!Person::players[closest]->skeleton.free)
                         flatvelocity2 = Person::players[closest]->velocity;
                     if (Person::players[closest]->skeleton.free)
@@ -2092,7 +1970,7 @@ void doDebugKeys()
                                 Person::players[j]->skeleton.free = 1;
                             Person::players[j]->skeleton.longdead = 0;
                             Person::players[j]->RagDoll(0);
-                            for (int i = 0; i < Person::players[j]->skeleton.num_joints; i++) {
+                            for (int i = 0; i < Person::players[j]->skeleton.joints.size(); i++) {
                                 temppos = Person::players[j]->skeleton.joints[i].position + Person::players[j]->coords;
                                 if (distsq(&temppos, &Person::players[closest]->coords) < 25) {
                                     flatvelocity2 = temppos - Person::players[closest]->coords;
@@ -2115,32 +1993,8 @@ void doDebugKeys()
             }
         }
 
-        if (Input::isKeyPressed(SDL_SCANCODE_F)) {
-            Person::players[0]->onfire = 1 - Person::players[0]->onfire;
-            if (Person::players[0]->onfire) {
-                Person::players[0]->CatchFire();
-            }
-            if (!Person::players[0]->onfire) {
-                emit_sound_at(fireendsound, Person::players[0]->coords);
-                pause_sound(stream_firesound);
-            }
-        }
-
-        if (Input::isKeyPressed(SDL_SCANCODE_N) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
-            Person::players[0]->RagDoll(0);
-
-            emit_sound_at(whooshsound, Person::players[0]->coords, 128.);
-        }
-
-        if (Input::isKeyPressed(SDL_SCANCODE_N) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
-            for (int i = 0; i < objects.numobjects; i++) {
-                if (objects.type[i] == treeleavestype) {
-                    objects.scale[i] *= .9;
-                }
-            }
-        }
-
-        if (Input::isKeyPressed(SDL_SCANCODE_M) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
+        /* Enable editor */
+        if (Input::isKeyPressed(SDL_SCANCODE_M) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
             editorenabled = !editorenabled;
             if (editorenabled) {
                 Person::players[0]->damagetolerance = 100000;
@@ -2153,315 +2007,283 @@ void doDebugKeys()
             Person::players[0]->bloodloss = 0;
             Person::players[0]->deathbleeding = 0;
         }
+    }
 
-        //skip level
-        if (whichlevel != -2 && Input::isKeyPressed(SDL_SCANCODE_K) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !editorenabled) {
-            targetlevel++;
-            if (targetlevel > numchallengelevels - 1)
-                targetlevel = 0;
-            loading = 1;
-            leveltime = 5;
-        }
+    //skip level
+    if (whichlevel != -2 && Input::isKeyPressed(SDL_SCANCODE_K) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !editorenabled) {
+        targetlevel++;
+        if (targetlevel > numchallengelevels - 1)
+            targetlevel = 0;
+        loading = 1;
+        leveltime = 5;
+    }
 
-        if (editorenabled) {
-            if (Input::isKeyPressed(SDL_SCANCODE_DELETE) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
-                int closest = findClosestPlayer();
-                if (closest >= 0) {
-                    Person::players.erase(Person::players.begin()+closest);
-                }
+    if (editorenabled) {
+        if (Input::isKeyPressed(SDL_SCANCODE_DELETE) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
+            int closest = findClosestPlayer();
+            if (closest >= 0) {
+                Person::players.erase(Person::players.begin()+closest);
             }
+        }
 
-            if (Input::isKeyPressed(SDL_SCANCODE_DELETE) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
-                int closest = findClosestObject();
-                if (closest >= 0)
-                    objects.position[closest].y -= 500;
-            }
+        if (Input::isKeyPressed(SDL_SCANCODE_DELETE) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
+            int closest = findClosestObject();
+            if (closest >= 0)
+                objects.position[closest].y -= 500;
+        }
 
-            if (Input::isKeyPressed(SDL_SCANCODE_M) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
-                if (objects.numobjects < max_objects - 1) {
-                    XYZ scenecoords;
-                    scenecoords.x = Person::players[0]->coords.x;
-                    scenecoords.z = Person::players[0]->coords.z;
-                    scenecoords.y = Person::players[0]->coords.y - 3;
-                    if (editortype == bushtype)
-                        scenecoords.y = Person::players[0]->coords.y - .5;
-                    if (editortype == firetype)
-                        scenecoords.y = Person::players[0]->coords.y - .5;
-                    //objects.MakeObject(abs(Random()%3),scenecoords,Random()%360);
-                    float temprotat, temprotat2;
-                    temprotat = editoryaw;
-                    temprotat2 = editorpitch;
-                    if (temprotat < 0 || editortype == bushtype)
-                        temprotat = Random() % 360;
-                    if (temprotat2 < 0)
-                        temprotat2 = Random() % 360;
-
-                    objects.MakeObject(editortype, scenecoords, (int)temprotat - ((int)temprotat) % 30, (int)temprotat2, editorsize);
-                    if (editortype == treetrunktype)
-                        objects.MakeObject(treeleavestype, scenecoords, Random() % 360 * (temprotat2 < 2) + (int)editoryaw - ((int)editoryaw) % 30, editorpitch, editorsize);
-                }
+        if (Input::isKeyPressed(SDL_SCANCODE_M) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
+            if (objects.numobjects < max_objects - 1) {
+                XYZ scenecoords;
+                scenecoords.x = Person::players[0]->coords.x;
+                scenecoords.z = Person::players[0]->coords.z;
+                scenecoords.y = Person::players[0]->coords.y - 3;
+                if (editortype == bushtype)
+                    scenecoords.y = Person::players[0]->coords.y - .5;
+                if (editortype == firetype)
+                    scenecoords.y = Person::players[0]->coords.y - .5;
+                //objects.MakeObject(abs(Random()%3),scenecoords,Random()%360);
+                float temprotat, temprotat2;
+                temprotat = editoryaw;
+                temprotat2 = editorpitch;
+                if (temprotat < 0 || editortype == bushtype)
+                    temprotat = Random() % 360;
+                if (temprotat2 < 0)
+                    temprotat2 = Random() % 360;
+
+                objects.MakeObject(editortype, scenecoords, (int)temprotat - ((int)temprotat) % 30, (int)temprotat2, editorsize);
+                if (editortype == treetrunktype)
+                    objects.MakeObject(treeleavestype, scenecoords, Random() % 360 * (temprotat2 < 2) + (int)editoryaw - ((int)editoryaw) % 30, editorpitch, editorsize);
             }
+        }
 
-            if (Input::isKeyPressed(SDL_SCANCODE_P) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
-                Person::players.push_back(shared_ptr<Person>(new Person()));
-
-                Person::players.back()->scale = .2 * 5 * Person::players[0]->scale;
-                Person::players.back()->creature = rabbittype;
-                Person::players.back()->howactive = editoractive;
-                Person::players.back()->skeleton.id = Person::players.size()-1;
-                Person::players.back()->skeleton.Load((char *)"Skeleton/BasicFigure", (char *)"Skeleton/BasicFigureLow", (char *)"Skeleton/RabbitBelt", (char *)"Models/Body.solid", (char *)"Models/Body2.solid", (char *)"Models/Body3.solid", (char *)"Models/Body4.solid", (char *)"Models/Body5.solid", (char *)"Models/Body6.solid", (char *)"Models/Body7.solid", (char *)"Models/BodyLow.solid", (char *)"Models/Belt.solid", 1);
-
-                int k = abs(Random() % 2) + 1;
-                if (k == 0) {
-                    Person::players.back()->skeleton.drawmodel.textureptr.load("Textures/Fur3.jpg", 1, &Person::players.back()->skeleton.skinText[0], &Person::players.back()->skeleton.skinsize);
-                    Person::players.back()->whichskin = 0;
-                } else if (k == 1) {
-                    Person::players.back()->skeleton.drawmodel.textureptr.load("Textures/Fur.jpg", 1, &Person::players.back()->skeleton.skinText[0], &Person::players.back()->skeleton.skinsize);
-                    Person::players.back()->whichskin = 1;
-                } else {
-                    Person::players.back()->skeleton.drawmodel.textureptr.load("Textures/Fur2.jpg", 1, &Person::players.back()->skeleton.skinText[0], &Person::players.back()->skeleton.skinsize);
-                    Person::players.back()->whichskin = 2;
-                }
+        if (Input::isKeyPressed(SDL_SCANCODE_P) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
+            Person::players.push_back(shared_ptr<Person>(new Person()));
 
-                Person::players.back()->skeleton.drawmodelclothes.textureptr.load("Textures/Belt.png", 1);
-                Person::players.back()->power = 1;
-                Person::players.back()->speedmult = 1;
-                Person::players.back()->animCurrent = bounceidleanim;
-                Person::players.back()->animTarget = bounceidleanim;
-                Person::players.back()->frameCurrent = 0;
-                Person::players.back()->frameTarget = 1;
-                Person::players.back()->target = 0;
-                Person::players.back()->bled = 0;
-                Person::players.back()->speed = 1 + (float)(Random() % 100) / 1000;
-
-                Person::players.back()->targetyaw = Person::players[0]->targetyaw;
-                Person::players.back()->yaw = Person::players[0]->yaw;
-
-                Person::players.back()->velocity = 0;
-                Person::players.back()->coords = Person::players[0]->coords;
-                Person::players.back()->oldcoords = Person::players.back()->coords;
-                Person::players.back()->realoldcoords = Person::players.back()->coords;
-
-                Person::players.back()->id = Person::players.size()-1;
-                Person::players.back()->updatedelay = 0;
-                Person::players.back()->normalsupdatedelay = 0;
-
-                Person::players.back()->aitype = passivetype;
-
-                if (Person::players[0]->creature == wolftype) {
-                    headprop = Person::players[0]->proportionhead.x / 1.1;
-                    bodyprop = Person::players[0]->proportionbody.x / 1.1;
-                    armprop = Person::players[0]->proportionarms.x / 1.1;
-                    legprop = Person::players[0]->proportionlegs.x / 1.1;
-                }
+            Person::players.back()->id = Person::players.size()-1;
 
-                if (Person::players[0]->creature == rabbittype) {
-                    headprop = Person::players[0]->proportionhead.x / 1.2;
-                    bodyprop = Person::players[0]->proportionbody.x / 1.05;
-                    armprop = Person::players[0]->proportionarms.x / 1.00;
-                    legprop = Person::players[0]->proportionlegs.x / 1.1;
-                }
+            Person::players.back()->scale = Person::players[0]->scale;
+            Person::players.back()->creature = rabbittype;
+            Person::players.back()->howactive = editoractive;
 
-                if (Person::players.back()->creature == wolftype) {
-                    Person::players.back()->proportionhead = 1.1 * headprop;
-                    Person::players.back()->proportionbody = 1.1 * bodyprop;
-                    Person::players.back()->proportionarms = 1.1 * armprop;
-                    Person::players.back()->proportionlegs = 1.1 * legprop;
-                }
-
-                if (Person::players.back()->creature == rabbittype) {
-                    Person::players.back()->proportionhead = 1.2 * headprop;
-                    Person::players.back()->proportionbody = 1.05 * bodyprop;
-                    Person::players.back()->proportionarms = 1.00 * armprop;
-                    Person::players.back()->proportionlegs = 1.1 * legprop;
-                    Person::players.back()->proportionlegs.y = 1.05 * legprop;
-                }
+            int k = abs(Random() % 2) + 1;
+            if (k == 0) {
+                Person::players.back()->whichskin = 0;
+            } else if (k == 1) {
+                Person::players.back()->whichskin = 1;
+            } else {
+                Person::players.back()->whichskin = 2;
+            }
 
-                Person::players.back()->headless = 0;
-                Person::players.back()->onfire = 0;
+            Person::players.back()->skeletonLoad(true);
 
-                if (cellophane) {
-                    Person::players.back()->proportionhead.z = 0;
-                    Person::players.back()->proportionbody.z = 0;
-                    Person::players.back()->proportionarms.z = 0;
-                    Person::players.back()->proportionlegs.z = 0;
-                }
+            Person::players.back()->skeleton.drawmodelclothes.textureptr.load("Textures/Belt.png", 1);
+            Person::players.back()->speed = 1 + (float)(Random() % 100) / 1000;
 
-                Person::players.back()->tempanimation.Load((char *)"Tempanim", 0, 0);
+            Person::players.back()->targetyaw = Person::players[0]->targetyaw;
+            Person::players.back()->yaw = Person::players[0]->yaw;
 
-                Person::players.back()->damagetolerance = 200;
+            Person::players.back()->coords = Person::players[0]->coords;
+            Person::players.back()->oldcoords = Person::players.back()->coords;
+            Person::players.back()->realoldcoords = Person::players.back()->coords;
 
-                Person::players.back()->protectionhead = Person::players[0]->protectionhead;
-                Person::players.back()->protectionhigh = Person::players[0]->protectionhigh;
-                Person::players.back()->protectionlow = Person::players[0]->protectionlow;
-                Person::players.back()->armorhead = Person::players[0]->armorhead;
-                Person::players.back()->armorhigh = Person::players[0]->armorhigh;
-                Person::players.back()->armorlow = Person::players[0]->armorlow;
-                Person::players.back()->metalhead = Person::players[0]->metalhead;
-                Person::players.back()->metalhigh = Person::players[0]->metalhigh;
-                Person::players.back()->metallow = Person::players[0]->metallow;
+            if (Person::players[0]->creature == wolftype) {
+                headprop = Person::players[0]->proportionhead.x / 1.1;
+                bodyprop = Person::players[0]->proportionbody.x / 1.1;
+                armprop = Person::players[0]->proportionarms.x / 1.1;
+                legprop = Person::players[0]->proportionlegs.x / 1.1;
+            }
 
-                Person::players.back()->immobile = Person::players[0]->immobile;
+            if (Person::players[0]->creature == rabbittype) {
+                headprop = Person::players[0]->proportionhead.x / 1.2;
+                bodyprop = Person::players[0]->proportionbody.x / 1.05;
+                armprop = Person::players[0]->proportionarms.x / 1.00;
+                legprop = Person::players[0]->proportionlegs.x / 1.1;
+            }
 
-                Person::players.back()->numclothes = Person::players[0]->numclothes;
-                for (int i = 0; i < Person::players.back()->numclothes; i++) {
-                    strcpy(Person::players.back()->clothes[i], Person::players[0]->clothes[i]);
-                    Person::players.back()->clothestintr[i] = Person::players[0]->clothestintr[i];
-                    Person::players.back()->clothestintg[i] = Person::players[0]->clothestintg[i];
-                    Person::players.back()->clothestintb[i] = Person::players[0]->clothestintb[i];
-                }
-                Person::players.back()->addClothes();
-
-                Person::players.back()->power = Person::players[0]->power;
-                Person::players.back()->speedmult = Person::players[0]->speedmult;
-
-                Person::players.back()->damage = 0;
-                Person::players.back()->permanentdamage = 0;
-                Person::players.back()->superpermanentdamage = 0;
-                Person::players.back()->deathbleeding = 0;
-                Person::players.back()->bleeding = 0;
-                Person::players.back()->numwaypoints = 0;
-                Person::players.back()->waypoint = 0;
-                Person::players.back()->weaponstuck = -1;
-                Person::players.back()->weaponactive = -1;
-                Person::players.back()->num_weapons = 0;
-                Person::players.back()->bloodloss = 0;
-                Person::players.back()->dead = 0;
-
-                Person::players.back()->loaded = 1;
+            if (Person::players.back()->creature == wolftype) {
+                Person::players.back()->proportionhead = 1.1 * headprop;
+                Person::players.back()->proportionbody = 1.1 * bodyprop;
+                Person::players.back()->proportionarms = 1.1 * armprop;
+                Person::players.back()->proportionlegs = 1.1 * legprop;
             }
 
-            if (Input::isKeyPressed(SDL_SCANCODE_P) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
-                if (Person::players.back()->numwaypoints < 90) {
-                    Person::players.back()->waypoints[Person::players.back()->numwaypoints] = Person::players[0]->coords;
-                    Person::players.back()->waypointtype[Person::players.back()->numwaypoints] = editorpathtype;
-                    Person::players.back()->numwaypoints++;
-                }
+            if (Person::players.back()->creature == rabbittype) {
+                Person::players.back()->proportionhead = 1.2 * headprop;
+                Person::players.back()->proportionbody = 1.05 * bodyprop;
+                Person::players.back()->proportionarms = 1.00 * armprop;
+                Person::players.back()->proportionlegs = 1.1 * legprop;
+                Person::players.back()->proportionlegs.y = 1.05 * legprop;
             }
 
-            if (Input::isKeyPressed(SDL_SCANCODE_P) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
-                if (numpathpoints < 30) {
-                    bool connected, alreadyconnected;
-                    connected = 0;
-                    if (numpathpoints > 1)
-                        for (int i = 0; i < numpathpoints; i++) {
-                            if (distsq(&pathpoint[i], &Person::players[0]->coords) < .5 && i != pathpointselected && !connected) {
-                                alreadyconnected = 0;
-                                for (int j = 0; j < numpathpointconnect[pathpointselected]; j++) {
-                                    if (pathpointconnect[pathpointselected][j] == i)
-                                        alreadyconnected = 1;
-                                }
-                                if (!alreadyconnected) {
-                                    numpathpointconnect[pathpointselected]++;
-                                    connected = 1;
-                                    pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected] - 1] = i;
-                                }
-                            }
-                        }
-                    if (!connected) {
-                        numpathpoints++;
-                        pathpoint[numpathpoints - 1] = Person::players[0]->coords;
-                        numpathpointconnect[numpathpoints - 1] = 0;
-                        if (numpathpoints > 1 && pathpointselected != -1) {
-                            numpathpointconnect[pathpointselected]++;
-                            pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected] - 1] = numpathpoints - 1;
-                        }
-                        pathpointselected = numpathpoints - 1;
-                    }
-                }
+            if (cellophane) {
+                Person::players.back()->proportionhead.z = 0;
+                Person::players.back()->proportionbody.z = 0;
+                Person::players.back()->proportionarms.z = 0;
+                Person::players.back()->proportionlegs.z = 0;
             }
 
-            if (Input::isKeyPressed(SDL_SCANCODE_PERIOD)) {
-                pathpointselected++;
-                if (pathpointselected >= numpathpoints)
-                    pathpointselected = -1;
+            Person::players.back()->tempanimation = Animation("Tempanim", lowheight, neutral);
+
+            Person::players.back()->damagetolerance = 200;
+
+            Person::players.back()->protectionhead = Person::players[0]->protectionhead;
+            Person::players.back()->protectionhigh = Person::players[0]->protectionhigh;
+            Person::players.back()->protectionlow = Person::players[0]->protectionlow;
+            Person::players.back()->armorhead = Person::players[0]->armorhead;
+            Person::players.back()->armorhigh = Person::players[0]->armorhigh;
+            Person::players.back()->armorlow = Person::players[0]->armorlow;
+            Person::players.back()->metalhead = Person::players[0]->metalhead;
+            Person::players.back()->metalhigh = Person::players[0]->metalhigh;
+            Person::players.back()->metallow = Person::players[0]->metallow;
+
+            Person::players.back()->immobile = Person::players[0]->immobile;
+
+            Person::players.back()->numclothes = Person::players[0]->numclothes;
+            for (int i = 0; i < Person::players.back()->numclothes; i++) {
+                strcpy(Person::players.back()->clothes[i], Person::players[0]->clothes[i]);
+                Person::players.back()->clothestintr[i] = Person::players[0]->clothestintr[i];
+                Person::players.back()->clothestintg[i] = Person::players[0]->clothestintg[i];
+                Person::players.back()->clothestintb[i] = Person::players[0]->clothestintb[i];
             }
-            if (Input::isKeyPressed(SDL_SCANCODE_COMMA) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
-                pathpointselected--;
-                if (pathpointselected <= -2)
-                    pathpointselected = numpathpoints - 1;
+            Person::players.back()->addClothes();
+
+            Person::players.back()->power = Person::players[0]->power;
+            Person::players.back()->speedmult = Person::players[0]->speedmult;
+
+            Person::players.back()->loaded = true;
+        }
+
+        if (Input::isKeyPressed(SDL_SCANCODE_P) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
+            if (Person::players.back()->numwaypoints < 90) {
+                Person::players.back()->waypoints[Person::players.back()->numwaypoints] = Person::players[0]->coords;
+                Person::players.back()->waypointtype[Person::players.back()->numwaypoints] = editorpathtype;
+                Person::players.back()->numwaypoints++;
             }
-            if (Input::isKeyPressed(SDL_SCANCODE_COMMA) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
-                if (pathpointselected != -1) {
-                    numpathpoints--;
-                    pathpoint[pathpointselected] = pathpoint[numpathpoints];
-                    numpathpointconnect[pathpointselected] = numpathpointconnect[numpathpoints];
-                    for (int i = 0; i < numpathpointconnect[pathpointselected]; i++) {
-                        pathpointconnect[pathpointselected][i] = pathpointconnect[numpathpoints][i];
-                    }
+        }
+
+        if (Input::isKeyPressed(SDL_SCANCODE_P) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
+            if (numpathpoints < 30) {
+                bool connected, alreadyconnected;
+                connected = 0;
+                if (numpathpoints > 1)
                     for (int i = 0; i < numpathpoints; i++) {
-                        for (int j = 0; j < numpathpointconnect[i]; j++) {
-                            if (pathpointconnect[i][j] == pathpointselected) {
-                                pathpointconnect[i][j] = pathpointconnect[i][numpathpointconnect[i] - 1];
-                                numpathpointconnect[i]--;
+                        if (distsq(&pathpoint[i], &Person::players[0]->coords) < .5 && i != pathpointselected && !connected) {
+                            alreadyconnected = 0;
+                            for (int j = 0; j < numpathpointconnect[pathpointselected]; j++) {
+                                if (pathpointconnect[pathpointselected][j] == i)
+                                    alreadyconnected = 1;
                             }
-                            if (pathpointconnect[i][j] == numpathpoints) {
-                                pathpointconnect[i][j] = pathpointselected;
+                            if (!alreadyconnected) {
+                                numpathpointconnect[pathpointselected]++;
+                                connected = 1;
+                                pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected] - 1] = i;
                             }
                         }
                     }
+                if (!connected) {
+                    numpathpoints++;
+                    pathpoint[numpathpoints - 1] = Person::players[0]->coords;
+                    numpathpointconnect[numpathpoints - 1] = 0;
+                    if (numpathpoints > 1 && pathpointselected != -1) {
+                        numpathpointconnect[pathpointselected]++;
+                        pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected] - 1] = numpathpoints - 1;
+                    }
                     pathpointselected = numpathpoints - 1;
                 }
             }
+        }
 
-            if (Input::isKeyPressed(SDL_SCANCODE_LEFT) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
-                editortype--;
-                if (editortype == treeleavestype || editortype == 10)
-                    editortype--;
-                if (editortype < 0)
-                    editortype = firetype;
+        if (Input::isKeyPressed(SDL_SCANCODE_PERIOD)) {
+            pathpointselected++;
+            if (pathpointselected >= numpathpoints)
+                pathpointselected = -1;
+        }
+        if (Input::isKeyPressed(SDL_SCANCODE_COMMA) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
+            pathpointselected--;
+            if (pathpointselected <= -2)
+                pathpointselected = numpathpoints - 1;
+        }
+        if (Input::isKeyPressed(SDL_SCANCODE_COMMA) && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
+            if (pathpointselected != -1) {
+                numpathpoints--;
+                pathpoint[pathpointselected] = pathpoint[numpathpoints];
+                numpathpointconnect[pathpointselected] = numpathpointconnect[numpathpoints];
+                for (int i = 0; i < numpathpointconnect[pathpointselected]; i++) {
+                    pathpointconnect[pathpointselected][i] = pathpointconnect[numpathpoints][i];
+                }
+                for (int i = 0; i < numpathpoints; i++) {
+                    for (int j = 0; j < numpathpointconnect[i]; j++) {
+                        if (pathpointconnect[i][j] == pathpointselected) {
+                            pathpointconnect[i][j] = pathpointconnect[i][numpathpointconnect[i] - 1];
+                            numpathpointconnect[i]--;
+                        }
+                        if (pathpointconnect[i][j] == numpathpoints) {
+                            pathpointconnect[i][j] = pathpointselected;
+                        }
+                    }
+                }
+                pathpointselected = numpathpoints - 1;
             }
+        }
+
+        if (Input::isKeyPressed(SDL_SCANCODE_LEFT) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
+            editortype--;
+            if (editortype == treeleavestype || editortype == 10)
+                editortype--;
+            if (editortype < 0)
+                editortype = firetype;
+        }
 
-            if (Input::isKeyPressed(SDL_SCANCODE_RIGHT) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
+        if (Input::isKeyPressed(SDL_SCANCODE_RIGHT) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
+            editortype++;
+            if (editortype == treeleavestype || editortype == 10)
                 editortype++;
-                if (editortype == treeleavestype || editortype == 10)
-                    editortype++;
-                if (editortype > firetype)
-                    editortype = 0;
-            }
+            if (editortype > firetype)
+                editortype = 0;
+        }
 
-            if (Input::isKeyDown(SDL_SCANCODE_LEFT) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
-                editoryaw -= multiplier * 100;
-                if (editoryaw < -.01)
-                    editoryaw = -.01;
-            }
+        if (Input::isKeyDown(SDL_SCANCODE_LEFT) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
+            editoryaw -= multiplier * 100;
+            if (editoryaw < -.01)
+                editoryaw = -.01;
+        }
 
-            if (Input::isKeyDown(SDL_SCANCODE_RIGHT) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
-                editoryaw += multiplier * 100;
-            }
+        if (Input::isKeyDown(SDL_SCANCODE_RIGHT) && !Input::isKeyDown(SDL_SCANCODE_LSHIFT) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
+            editoryaw += multiplier * 100;
+        }
 
-            if (Input::isKeyDown(SDL_SCANCODE_UP) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
-                editorsize += multiplier;
-            }
+        if (Input::isKeyDown(SDL_SCANCODE_UP) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
+            editorsize += multiplier;
+        }
 
-            if (Input::isKeyDown(SDL_SCANCODE_DOWN) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
-                editorsize -= multiplier;
-                if (editorsize < .1)
-                    editorsize = .1;
-            }
+        if (Input::isKeyDown(SDL_SCANCODE_DOWN) && !Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
+            editorsize -= multiplier;
+            if (editorsize < .1)
+                editorsize = .1;
+        }
 
 
-            if (Input::isKeyPressed(SDL_SCANCODE_LEFT) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
-                mapradius -= multiplier * 10;
-            }
+        if (Input::isKeyPressed(SDL_SCANCODE_LEFT) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
+            mapradius -= multiplier * 10;
+        }
 
-            if (Input::isKeyPressed(SDL_SCANCODE_RIGHT) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
-                mapradius += multiplier * 10;
-            }
-            if (Input::isKeyDown(SDL_SCANCODE_UP) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
-                editorpitch += multiplier * 100;
-            }
+        if (Input::isKeyPressed(SDL_SCANCODE_RIGHT) && Input::isKeyDown(SDL_SCANCODE_LSHIFT) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
+            mapradius += multiplier * 10;
+        }
+        if (Input::isKeyDown(SDL_SCANCODE_UP) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
+            editorpitch += multiplier * 100;
+        }
 
-            if (Input::isKeyDown(SDL_SCANCODE_DOWN) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
-                editorpitch -= multiplier * 100;
-                if (editorpitch < -.01)
-                    editorpitch = -.01;
-            }
-            if (Input::isKeyPressed(SDL_SCANCODE_DELETE) && objects.numobjects && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
-                int closest = findClosestObject();
-                if (closest >= 0)
-                    objects.DeleteObject(closest);
-            }
+        if (Input::isKeyDown(SDL_SCANCODE_DOWN) && Input::isKeyDown(SDL_SCANCODE_LCTRL)) {
+            editorpitch -= multiplier * 100;
+            if (editorpitch < -.01)
+                editorpitch = -.01;
+        }
+        if (Input::isKeyPressed(SDL_SCANCODE_DELETE) && objects.numobjects && Input::isKeyDown(SDL_SCANCODE_LSHIFT)) {
+            int closest = findClosestObject();
+            if (closest >= 0)
+                objects.DeleteObject(closest);
         }
     }
 }
@@ -2486,7 +2308,7 @@ void doJumpReversals()
                     if (Person::players[i]->animTarget == jumpupanim &&
                             Person::players[k]->animTarget != getupfrombackanim &&
                             Person::players[k]->animTarget != getupfromfrontanim &&
-                            animation[Person::players[k]->animTarget].height == middleheight &&
+                            Animation::animations[Person::players[k]->animTarget].height == middleheight &&
                             normaldotproduct(Person::players[i]->velocity, Person::players[k]->coords - Person::players[i]->coords) < 0 &&
                             ((Person::players[k]->aitype == playercontrolled && Person::players[k]->attackkeydown) ||
                              Person::players[k]->aitype != playercontrolled)) {
@@ -2525,7 +2347,7 @@ void doJumpReversals()
                     if (Person::players[k]->animTarget == jumpupanim &&
                             Person::players[i]->animTarget != getupfrombackanim &&
                             Person::players[i]->animTarget != getupfromfrontanim &&
-                            animation[Person::players[i]->animTarget].height == middleheight &&
+                            Animation::animations[Person::players[i]->animTarget].height == middleheight &&
                             normaldotproduct(Person::players[k]->velocity, Person::players[i]->coords - Person::players[k]->coords) < 0 &&
                             ((Person::players[i]->aitype == playercontrolled && Person::players[i]->attackkeydown) ||
                              Person::players[i]->aitype != playercontrolled)) {
@@ -2593,7 +2415,7 @@ void doAerialAcrobatics()
                 Person::players[k]->animTarget == backhandspringanim ||
                 Person::players[k]->animTarget == dodgebackanim ||
                 Person::players[k]->animTarget == rollanim ||
-                (animation[Person::players[k]->animTarget].attack &&
+                (Animation::animations[Person::players[k]->animTarget].attack &&
                  Person::players[k]->animTarget != rabbitkickanim &&
                  (Person::players[k]->animTarget != crouchstabanim || Person::players[k]->hasvictim) &&
                  (Person::players[k]->animTarget != swordgroundstabanim || Person::players[k]->hasvictim))) {
@@ -2744,7 +2566,7 @@ void doAerialAcrobatics()
 
                         if (Person::players[k]->animTarget == jumpdownanim || Person::players[k]->isFlip()) {
                             //flipped into a rock
-                            if (Person::players[k]->isFlip() && animation[Person::players[k]->animTarget].label[Person::players[k]->frameTarget] == 7)
+                            if (Person::players[k]->isFlip() && Person::players[k]->targetFrame().label == 7)
                                 Person::players[k]->RagDoll(0);
 
                             if (Person::players[k]->animTarget == jumpupanim) {
@@ -3022,7 +2844,7 @@ void doAttacks()
                     }
                 }
                 //attack
-                if (!animation[Person::players[k]->animTarget].attack &&
+                if (!Animation::animations[Person::players[k]->animTarget].attack &&
                         !Person::players[k]->backkeydown &&
                         (Person::players[k]->isIdle() ||
                          Person::players[k]->isRun() ||
@@ -3037,7 +2859,7 @@ void doAttacks()
                             if (i == k || !(k == 0 || i == 0))
                                 continue;
                             if (!Person::players[k]->hasvictim)
-                                if (animation[Person::players[k]->animTarget].attack != reversal) {
+                                if (Animation::animations[Person::players[k]->animTarget].attack != reversal) {
                                     //choose an attack
                                     const float distance = distsq(&Person::players[k]->coords, &Person::players[i]->coords);
                                     if (distance < 4.5 &&
@@ -3049,8 +2871,7 @@ void doAttacks()
                                             Person::players[k]->animTarget != rabbitkickanim &&
                                             Person::players[i]->animTarget != getupfrombackanim &&
                                             (Person::players[i]->animTarget != staggerbackhighanim &&
-                                             (Person::players[i]->animTarget != staggerbackhardanim ||
-                                              animation[staggerbackhardanim].label[Person::players[i]->frameTarget] == 6)) &&
+                                             (Person::players[i]->animTarget != staggerbackhardanim || Person::players[i]->targetFrame().label == 6)) &&
                                             Person::players[i]->animTarget != jumpdownanim &&
                                             Person::players[i]->animTarget != jumpupanim &&
                                             Person::players[i]->animTarget != getupfromfrontanim) {
@@ -3060,11 +2881,11 @@ void doAttacks()
                                             //sweep
                                             if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
                                                     Person::players[k]->crouchkeydown &&
-                                                    animation[Person::players[i]->animTarget].height != lowheight)
+                                                    Animation::animations[Person::players[i]->animTarget].height != lowheight)
                                                 Person::players[k]->animTarget = sweepanim;
                                             //winduppunch
                                             else if (distance < 1.5 * sq(Person::players[k]->scale * 5) &&
-                                                     animation[Person::players[i]->animTarget].height != lowheight &&
+                                                     Animation::animations[Person::players[i]->animTarget].height != lowheight &&
                                                      !Person::players[k]->forwardkeydown &&
                                                      !Person::players[k]->leftkeydown &&
                                                      !Person::players[k]->rightkeydown &&
@@ -3074,7 +2895,7 @@ void doAttacks()
                                                 Person::players[k]->animTarget = winduppunchanim;
                                             //upunch
                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
-                                                     animation[Person::players[i]->animTarget].height != lowheight &&
+                                                     Animation::animations[Person::players[i]->animTarget].height != lowheight &&
                                                      !Person::players[k]->forwardkeydown &&
                                                      !Person::players[k]->leftkeydown &&
                                                      !Person::players[k]->rightkeydown &&
@@ -3089,7 +2910,7 @@ void doAttacks()
                                                 Person::players[k]->animTarget = knifefollowanim;
                                             //knifeslashstart
                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
-                                                     animation[Person::players[i]->animTarget].height != lowheight &&
+                                                     Animation::animations[Person::players[i]->animTarget].height != lowheight &&
                                                      !Person::players[k]->forwardkeydown &&
                                                      !Person::players[k]->leftkeydown &&
                                                      !Person::players[k]->rightkeydown &&
@@ -3099,14 +2920,14 @@ void doAttacks()
                                                 Person::players[k]->animTarget = knifeslashstartanim;
                                             //swordslash
                                             else if (distance < 4.5 * sq(Person::players[k]->scale * 5) &&
-                                                     animation[Person::players[i]->animTarget].height != lowheight &&
+                                                     Animation::animations[Person::players[i]->animTarget].height != lowheight &&
                                                      !Person::players[k]->crouchkeydown &&
                                                      attackweapon == sword &&
                                                      Person::players[k]->weaponmissdelay <= 0)
                                                 Person::players[k]->animTarget = swordslashanim;
                                             //staffhit
                                             else if (distance < 4.5 * sq(Person::players[k]->scale * 5) &&
-                                                     animation[Person::players[i]->animTarget].height != lowheight &&
+                                                     Animation::animations[Person::players[i]->animTarget].height != lowheight &&
                                                      !Person::players[k]->crouchkeydown &&
                                                      attackweapon == staff &&
                                                      Person::players[k]->weaponmissdelay <= 0 &&
@@ -3116,36 +2937,36 @@ void doAttacks()
                                                 Person::players[k]->animTarget = staffhitanim;
                                             //staffspinhit
                                             else if (distance < 4.5 * sq(Person::players[k]->scale * 5) &&
-                                                     animation[Person::players[i]->animTarget].height != lowheight &&
+                                                     Animation::animations[Person::players[i]->animTarget].height != lowheight &&
                                                      !Person::players[k]->crouchkeydown &&
                                                      attackweapon == staff &&
                                                      Person::players[k]->weaponmissdelay <= 0)
                                                 Person::players[k]->animTarget = staffspinhitanim;
                                             //spinkick
                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
-                                                     animation[Person::players[i]->animTarget].height != lowheight)
+                                                     Animation::animations[Person::players[i]->animTarget].height != lowheight)
                                                 Person::players[k]->animTarget = spinkickanim;
                                             //lowkick
                                             else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
-                                                     animation[Person::players[i]->animTarget].height == lowheight &&
-                                                     animation[Person::players[k]->animTarget].attack != normalattack)
+                                                     Animation::animations[Person::players[i]->animTarget].height == lowheight &&
+                                                     Animation::animations[Person::players[k]->animTarget].attack != normalattack)
                                                 Person::players[k]->animTarget = lowkickanim;
                                         } else { //AI player
                                             if (distance < 4.5 * sq(Person::players[k]->scale * 5)) {
                                                 randattack = abs(Random() % 5);
                                                 if (!attackweapon && distance < 2.5 * sq(Person::players[k]->scale * 5)) {
                                                     //sweep
-                                                    if (randattack == 0 && animation[Person::players[i]->animTarget].height != lowheight)
+                                                    if (randattack == 0 && Animation::animations[Person::players[i]->animTarget].height != lowheight)
                                                         Person::players[k]->animTarget = sweepanim;
                                                     //upunch
-                                                    else if (randattack == 1 && animation[Person::players[i]->animTarget].height != lowheight &&
+                                                    else if (randattack == 1 && Animation::animations[Person::players[i]->animTarget].height != lowheight &&
                                                              !attackweapon)
                                                         Person::players[k]->animTarget = upunchanim;
                                                     //spinkick
-                                                    else if (randattack == 2 && animation[Person::players[i]->animTarget].height != lowheight)
+                                                    else if (randattack == 2 && Animation::animations[Person::players[i]->animTarget].height != lowheight)
                                                         Person::players[k]->animTarget = spinkickanim;
                                                     //lowkick
-                                                    else if (animation[Person::players[i]->animTarget].height == lowheight)
+                                                    else if (Animation::animations[Person::players[i]->animTarget].height == lowheight)
                                                         Person::players[k]->animTarget = lowkickanim;
                                                 }
                                                 if (attackweapon) {
@@ -3153,7 +2974,7 @@ void doAttacks()
                                                     if ((tutoriallevel != 1 || !attackweapon) &&
                                                             distance < 2.5 * sq(Person::players[k]->scale * 5) &&
                                                             randattack == 0 &&
-                                                            animation[Person::players[i]->animTarget].height != lowheight)
+                                                            Animation::animations[Person::players[i]->animTarget].height != lowheight)
                                                         Person::players[k]->animTarget = sweepanim;
                                                     //knifeslashstart
                                                     else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
@@ -3187,12 +3008,12 @@ void doAttacks()
                                                     else if ((tutoriallevel != 1 || !attackweapon) &&
                                                              distance < 2.5 * sq(Person::players[k]->scale * 5) &&
                                                              randattack == 1 &&
-                                                             animation[Person::players[i]->animTarget].height != lowheight)
+                                                             Animation::animations[Person::players[i]->animTarget].height != lowheight)
                                                         Person::players[k]->animTarget = spinkickanim;
                                                     //lowkick
                                                     else if (distance < 2.5 * sq(Person::players[k]->scale * 5) &&
-                                                             animation[Person::players[i]->animTarget].height == lowheight &&
-                                                             animation[Person::players[k]->animTarget].attack != normalattack)
+                                                             Animation::animations[Person::players[i]->animTarget].height == lowheight &&
+                                                             Animation::animations[Person::players[k]->animTarget].attack != normalattack)
                                                         Person::players[k]->animTarget = lowkickanim;
                                                 }
                                             }
@@ -3257,7 +3078,7 @@ void doAttacks()
                                             Person::players[i]->targetyaw = Person::players[i]->yaw;
                                         }
                                     }
-                                    if (animation[Person::players[k]->animTarget].attack == normalattack &&
+                                    if (Animation::animations[Person::players[k]->animTarget].attack == normalattack &&
                                             Person::players[k]->victim == Person::players[i] &&
                                             (!Person::players[i]->skeleton.free)) {
                                         oldattackkey = 1;
@@ -3307,7 +3128,7 @@ void doAttacks()
                             if (i == k)
                                 continue;
                             if ((playerrealattackkeydown || Person::players[i]->dead || !hasstaff) &&
-                                    animation[Person::players[k]->animTarget].attack == neutral) {
+                                    Animation::animations[Person::players[k]->animTarget].attack == neutral) {
                                 const float distance = distsq(&Person::players[k]->coords, &Person::players[i]->coords);
                                 if (!Person::players[i]->dead || !realthreat || (!attackweapon && Person::players[k]->crouchkeydown))
                                     if (Person::players[i]->skeleton.free)
@@ -3386,7 +3207,7 @@ void doAttacks()
                                                     }
                                                 }
                                         }
-                                if (animation[Person::players[k]->animTarget].attack == normalattack &&
+                                if (Animation::animations[Person::players[k]->animTarget].attack == normalattack &&
                                         Person::players[k]->victim == Person::players[i] &&
                                         (!Person::players[i]->skeleton.free ||
                                          Person::players[k]->animTarget == killanim ||
@@ -3454,7 +3275,7 @@ void doAttacks()
                                   !Person::players[k]->victim->skeleton.free &&
                                   Person::players[k]->victim->animTarget != getupfrombackanim &&
                                   Person::players[k]->victim->animTarget != getupfromfrontanim &&
-                                  animation[Person::players[k]->victim->animTarget].height != lowheight &&
+                                  Animation::animations[Person::players[k]->victim->animTarget].height != lowheight &&
                                   Person::players[k]->aitype != playercontrolled && //wat???
                                   normaldotproduct(Person::players[k]->facing, Person::players[k]->victim->coords - Person::players[k]->coords) > 0 &&
                                   Person::players[k]->rabbitkickenabled) ||
@@ -3463,7 +3284,7 @@ void doAttacks()
                             Person::players[k]->setAnimation(rabbitkickanim);
                         }
                     //update counts
-                    if (animation[Person::players[k]->animTarget].attack && k == 0) {
+                    if (Animation::animations[Person::players[k]->animTarget].attack && k == 0) {
                         numattacks++;
                         switch (attackweapon) {
                         case 0:
@@ -3494,14 +3315,14 @@ void doPlayerCollisions()
         for (unsigned k = 0; k < Person::players.size(); k++)
             for (unsigned i = k + 1; i < Person::players.size(); i++) {
                 //neither player is part of a reversal
-                if ((animation[Person::players[i]->animTarget].attack != reversed &&
-                        animation[Person::players[i]->animTarget].attack != reversal &&
-                        animation[Person::players[k]->animTarget].attack != reversed &&
-                        animation[Person::players[k]->animTarget].attack != reversal) || (i != 0 && k != 0))
-                    if ((animation[Person::players[i]->animCurrent].attack != reversed &&
-                            animation[Person::players[i]->animCurrent].attack != reversal &&
-                            animation[Person::players[k]->animCurrent].attack != reversed &&
-                            animation[Person::players[k]->animCurrent].attack != reversal) || (i != 0 && k != 0))
+                if ((Animation::animations[Person::players[i]->animTarget].attack != reversed &&
+                        Animation::animations[Person::players[i]->animTarget].attack != reversal &&
+                        Animation::animations[Person::players[k]->animTarget].attack != reversed &&
+                        Animation::animations[Person::players[k]->animTarget].attack != reversal) || (i != 0 && k != 0))
+                    if ((Animation::animations[Person::players[i]->animCurrent].attack != reversed &&
+                            Animation::animations[Person::players[i]->animCurrent].attack != reversal &&
+                            Animation::animations[Person::players[k]->animCurrent].attack != reversed &&
+                            Animation::animations[Person::players[k]->animCurrent].attack != reversal) || (i != 0 && k != 0))
                         //neither is sleeping
                         if (Person::players[i]->howactive <= typesleeping && Person::players[k]->howactive <= typesleeping)
                             if (Person::players[i]->howactive != typesittingwall && Person::players[k]->howactive != typesittingwall)
@@ -3581,16 +3402,16 @@ void doPlayerCollisions()
                                                                                 k == 0 && findLengthfast(&rotatetarget) > 50 && Person::players[0]->rabbitkickragdoll) &&
                                                                                 normaldotproduct(rotatetarget, Person::players[k]->coords - Person::players[i]->coords) > 0) &&
                                                                                 (k == 0 ||
-                                                                                 k != 0 && Person::players[i]->skeleton.oldfree == 1 && animation[Person::players[k]->animCurrent].attack == neutral ||
-                                                                                 /*i!=0&&*/Person::players[k]->skeleton.oldfree == 1 && animation[Person::players[i]->animCurrent].attack == neutral)) ||
+                                                                                 k != 0 && Person::players[i]->skeleton.oldfree == 1 && Animation::animations[Person::players[k]->animCurrent].attack == neutral ||
+                                                                                 /*i!=0&&*/Person::players[k]->skeleton.oldfree == 1 && Animation::animations[Person::players[i]->animCurrent].attack == neutral)) ||
                                                                                 (Person::players[i]->animTarget == jumpupanim || Person::players[i]->animTarget == jumpdownanim || Person::players[i]->isFlip()) &&
                                                                                 (Person::players[k]->animTarget == jumpupanim || Person::players[k]->animTarget == jumpdownanim || Person::players[k]->isFlip()) &&
                                                                                 k == 0 && !Person::players[i]->skeleton.oldfree && !Person::players[k]->skeleton.oldfree) {
                                                                             //If hit by body
                                                                             if (     (i != 0 || Person::players[i]->skeleton.free) &&
                                                                                      (k != 0 || Person::players[k]->skeleton.free) ||
-                                                                                     (animation[Person::players[i]->animTarget].height == highheight &&
-                                                                                      animation[Person::players[k]->animTarget].height == highheight)) {
+                                                                                     (Animation::animations[Person::players[i]->animTarget].height == highheight &&
+                                                                                      Animation::animations[Person::players[k]->animTarget].height == highheight)) {
                                                                                 if (tutoriallevel != 1) {
                                                                                     emit_sound_at(heavyimpactsound, Person::players[i]->coords);
                                                                                 }
@@ -3606,19 +3427,19 @@ void doPlayerCollisions()
                                                                                 }
                                                                                 Person::players[k]->DoDamage(findLengthfast(&rotatetarget) / 4);
 
-                                                                                for (int j = 0; j < Person::players[i]->skeleton.num_joints; j++) {
+                                                                                for (int j = 0; j < Person::players[i]->skeleton.joints.size(); j++) {
                                                                                     Person::players[i]->skeleton.joints[j].velocity = Person::players[i]->skeleton.joints[j].velocity / 5 + Person::players[k]->velocity;
                                                                                 }
-                                                                                for (int j = 0; j < Person::players[k]->skeleton.num_joints; j++) {
+                                                                                for (int j = 0; j < Person::players[k]->skeleton.joints.size(); j++) {
                                                                                     Person::players[k]->skeleton.joints[j].velocity = Person::players[k]->skeleton.joints[j].velocity / 5 + Person::players[i]->velocity;
                                                                                 }
 
                                                                             }
                                                                         }
-                                                                    if (     (animation[Person::players[i]->animTarget].attack == neutral ||
-                                                                              animation[Person::players[i]->animTarget].attack == normalattack) &&
-                                                                             (animation[Person::players[k]->animTarget].attack == neutral ||
-                                                                              animation[Person::players[k]->animTarget].attack == normalattack)) {
+                                                                    if (     (Animation::animations[Person::players[i]->animTarget].attack == neutral ||
+                                                                              Animation::animations[Person::players[i]->animTarget].attack == normalattack) &&
+                                                                             (Animation::animations[Person::players[k]->animTarget].attack == neutral ||
+                                                                              Animation::animations[Person::players[k]->animTarget].attack == normalattack)) {
                                                                         //If bumped
                                                                         if (Person::players[i]->skeleton.oldfree == 0 && Person::players[k]->skeleton.oldfree == 0) {
                                                                             if (distsq(&Person::players[k]->coords, &Person::players[i]->coords) < .5 * sq((Person::players[i]->scale + Person::players[k]->scale) * 2.5)) {
@@ -3839,12 +3660,12 @@ void doAI(unsigned i)
                     distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 400 &&
                     Person::players[i]->occluded < 25) {
                 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 12 &&
-                        animation[Person::players[0]->animTarget].height != lowheight &&
+                        Animation::animations[Person::players[0]->animTarget].height != lowheight &&
                         !editorenabled &&
                         (Person::players[0]->coords.y < Person::players[i]->coords.y + 5 || Person::players[0]->onterrain))
                     Person::players[i]->aitype = attacktypecutoff;
                 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 30 &&
-                        animation[Person::players[0]->animTarget].height == highheight &&
+                        Animation::animations[Person::players[0]->animTarget].height == highheight &&
                         !editorenabled)
                     Person::players[i]->aitype = attacktypecutoff;
 
@@ -3852,7 +3673,7 @@ void doAI(unsigned i)
                     Person::players[i]->losupdatedelay = .2;
                     for (unsigned j = 0; j < Person::players.size(); j++)
                         if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype)
-                            if (abs(Random() % 2) || animation[Person::players[j]->animTarget].height != lowheight || j != 0)
+                            if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
                                 if (distsq(&Person::players[i]->coords, &Person::players[j]->coords) < 400)
                                     if (normaldotproduct(Person::players[i]->facing, Person::players[j]->coords - Person::players[i]->coords) > 0)
                                         if (Person::players[j]->coords.y < Person::players[i]->coords.y + 5 || Person::players[j]->onterrain)
@@ -3962,10 +3783,10 @@ void doAI(unsigned i)
                     distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 400 &&
                     Person::players[i]->occluded < 25) {
                 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 12 &&
-                        animation[Person::players[0]->animTarget].height != lowheight && !editorenabled)
+                        Animation::animations[Person::players[0]->animTarget].height != lowheight && !editorenabled)
                     Person::players[i]->aitype = attacktypecutoff;
                 if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 30 &&
-                        animation[Person::players[0]->animTarget].height == highheight && !editorenabled)
+                        Animation::animations[Person::players[0]->animTarget].height == highheight && !editorenabled)
                     Person::players[i]->aitype = attacktypecutoff;
 
                 //wolf smell
@@ -3996,7 +3817,7 @@ void doAI(unsigned i)
                     Person::players[i]->losupdatedelay = .2;
                     for (unsigned j = 0; j < Person::players.size(); j++) {
                         if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
-                            if (abs(Random() % 2) || animation[Person::players[j]->animTarget].height != lowheight || j != 0)
+                            if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
                                 if (distsq(&Person::players[i]->coords, &Person::players[j]->coords) < 400)
                                     if (normaldotproduct(Person::players[i]->facing, Person::players[j]->coords - Person::players[i]->coords) > 0)
                                         if ((-1 == checkcollide(
@@ -4008,7 +3829,7 @@ void doAI(unsigned i)
                                                 (Person::players[j]->animTarget == hanganim &&
                                                  normaldotproduct(Person::players[j]->facing, Person::players[i]->coords - Person::players[j]->coords) < 0)) {
                                             Person::players[i]->lastseentime -= .2;
-                                            if (j == 0 && animation[Person::players[j]->animTarget].height == lowheight)
+                                            if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight)
                                                 Person::players[i]->lastseentime -= .4;
                                             else
                                                 Person::players[i]->lastseentime -= .6;
@@ -4130,11 +3951,11 @@ void doAI(unsigned i)
                     Person::players[i]->occluded < 2 &&
                     ((tutoriallevel != 1 || cananger) && hostile)) {
                 Person::players[i]->losupdatedelay = .2;
-                if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 4 && animation[Person::players[i]->animTarget].height != lowheight) {
+                if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 4 && Animation::animations[Person::players[i]->animTarget].height != lowheight) {
                     Person::players[i]->aitype = attacktypecutoff;
                     Person::players[i]->lastseentime = 1;
                 }
-                if (abs(Random() % 2) || animation[Person::players[i]->animTarget].height != lowheight)
+                if (abs(Random() % 2) || Animation::animations[Person::players[i]->animTarget].height != lowheight)
                     //TODO: factor out canSeePlayer()
                     if (distsq(&Person::players[i]->coords, &Person::players[0]->coords) < 400)
                         if (normaldotproduct(Person::players[i]->facing, Person::players[0]->coords - Person::players[i]->coords) > 0)
@@ -4412,7 +4233,7 @@ void doAI(unsigned i)
                         }
             //dodge/reverse walljump kicks
             if (Person::players[i]->damage < Person::players[i]->damagetolerance / 2)
-                if (animation[Person::players[i]->animTarget].height != highheight)
+                if (Animation::animations[Person::players[i]->animTarget].height != highheight)
                     if (Person::players[i]->damage < Person::players[i]->damagetolerance * .5 &&
                             ((Person::players[0]->animTarget == walljumprightkickanim ||
                               Person::players[0]->animTarget == walljumpleftkickanim) &&
@@ -4450,7 +4271,7 @@ void doAI(unsigned i)
                 }
             //lose sight of player in the air (?)
             if (Person::players[0]->coords.y > Person::players[i]->coords.y + 5 &&
-                    animation[Person::players[0]->animTarget].height != highheight &&
+                    Animation::animations[Person::players[0]->animTarget].height != highheight &&
                     !Person::players[0]->onterrain) {
                 Person::players[i]->aitype = pathfindtype;
                 Person::players[i]->finalfinaltarget = Person::players[i]->waypoints[Person::players[i]->waypoint];
@@ -4463,7 +4284,7 @@ void doAI(unsigned i)
             }
             //it's time to think (?)
             if (Person::players[i]->aiupdatedelay < 0 &&
-                    !animation[Person::players[i]->animTarget].attack &&
+                    !Animation::animations[Person::players[i]->animTarget].attack &&
                     Person::players[i]->animTarget != staggerbackhighanim &&
                     Person::players[i]->animTarget != staggerbackhardanim &&
                     Person::players[i]->animTarget != backhandspringanim &&
@@ -4612,7 +4433,7 @@ void doAI(unsigned i)
                         Person::players[i]->lastseentime = 1;
             }
         }
-        if (animation[Person::players[0]->animTarget].height == highheight &&
+        if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
                 (Person::players[i]->aitype == attacktypecutoff ||
                  Person::players[i]->aitype == searchtype))
             if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
@@ -4667,613 +4488,6 @@ void doAI(unsigned i)
     }
 }
 
-
-
-void updateSettingsMenu()
-{
-    char sbuf[256];
-    if ((float)newscreenwidth > (float)newscreenheight * 1.61 || (float)newscreenwidth < (float)newscreenheight * 1.59)
-        sprintf (sbuf, "Resolution: %d*%d", (int)newscreenwidth, (int)newscreenheight);
-    else
-        sprintf (sbuf, "Resolution: %d*%d (widescreen)", (int)newscreenwidth, (int)newscreenheight);
-    Menu::setText(0, sbuf);
-    Menu::setText(14, fullscreen ? "Fullscreen: On" : "Fullscreen: Off");
-    if (newdetail == 0) Menu::setText(1, "Detail: Low");
-    if (newdetail == 1) Menu::setText(1, "Detail: Medium");
-    if (newdetail == 2) Menu::setText(1, "Detail: High");
-    if (bloodtoggle == 0) Menu::setText(2, "Blood: Off");
-    if (bloodtoggle == 1) Menu::setText(2, "Blood: On, low detail");
-    if (bloodtoggle == 2) Menu::setText(2, "Blood: On, high detail (slower)");
-    if (difficulty == 0) Menu::setText(3, "Difficulty: Easier");
-    if (difficulty == 1) Menu::setText(3, "Difficulty: Difficult");
-    if (difficulty == 2) Menu::setText(3, "Difficulty: Insane");
-    Menu::setText(4, ismotionblur ? "Blur Effects: Enabled (less compatible)" : "Blur Effects: Disabled (more compatible)");
-    Menu::setText(5, decals ? "Decals: Enabled (slower)" : "Decals: Disabled");
-    Menu::setText(6, musictoggle ? "Music: Enabled" : "Music: Disabled");
-    Menu::setText(9, invertmouse ? "Invert mouse: Yes" : "Invert mouse: No");
-    sprintf (sbuf, "Mouse Speed: %d", (int)(usermousesensitivity * 5));
-    Menu::setText(10, sbuf);
-    sprintf (sbuf, "Volume: %d%%", (int)(volume * 100));
-    Menu::setText(11, sbuf);
-    Menu::setText(13, showdamagebar ? "Damage Bar: On" : "Damage Bar: Off");
-    if (newdetail == detail && newscreenheight == (int)screenheight && newscreenwidth == (int)screenwidth)
-        sprintf (sbuf, "Back");
-    else
-        sprintf (sbuf, "Back (some changes take effect next time Lugaru is opened)");
-    Menu::setText(8, sbuf);
-}
-
-void updateStereoConfigMenu()
-{
-    char sbuf[256];
-    sprintf(sbuf, "Stereo mode: %s", StereoModeName(newstereomode));
-    Menu::setText(0, sbuf);
-    sprintf(sbuf, "Stereo separation: %.3f", stereoseparation);
-    Menu::setText(1, sbuf);
-    sprintf(sbuf, "Reverse stereo: %s", stereoreverse ? "Yes" : "No");
-    Menu::setText(2, sbuf);
-}
-
-void updateControlsMenu()
-{
-    Menu::setText(0, (string)"Forwards: " + (keyselect == 0 ? "_" : Input::keyToChar(forwardkey)));
-    Menu::setText(1, (string)"Back: "    + (keyselect == 1 ? "_" : Input::keyToChar(backkey)));
-    Menu::setText(2, (string)"Left: "    + (keyselect == 2 ? "_" : Input::keyToChar(leftkey)));
-    Menu::setText(3, (string)"Right: "   + (keyselect == 3 ? "_" : Input::keyToChar(rightkey)));
-    Menu::setText(4, (string)"Crouch: "  + (keyselect == 4 ? "_" : Input::keyToChar(crouchkey)));
-    Menu::setText(5, (string)"Jump: "    + (keyselect == 5 ? "_" : Input::keyToChar(jumpkey)));
-    Menu::setText(6, (string)"Draw: "    + (keyselect == 6 ? "_" : Input::keyToChar(drawkey)));
-    Menu::setText(7, (string)"Throw: "   + (keyselect == 7 ? "_" : Input::keyToChar(throwkey)));
-    Menu::setText(8, (string)"Attack: "  + (keyselect == 8 ? "_" : Input::keyToChar(attackkey)));
-    if (debugmode)
-        Menu::setText(9, (string)"Console: " + (keyselect == 9 ? "_" : Input::keyToChar(consolekey)));
-}
-
-/*
-Values of mainmenu :
-1 Main menu
-2 Menu pause (resume/end game)
-3 Option menu
-4 Controls configuration menu
-5 Main game menu (choose level or challenge)
-6 Deleting user menu
-7 User managment menu (select/add)
-8 Choose difficulty menu
-9 Challenge level selection menu
-10 End of the campaign congratulation (is that really a menu?)
-11 Same that 9 ??? => unused
-18 stereo configuration
-*/
-
-void Game::LoadMenu()
-{
-    Menu::clearMenu();
-    switch (mainmenu) {
-    case 1:
-    case 2:
-        Menu::addImage(0, Mainmenuitems[0], 150, 480 - 128, 256, 128);
-        Menu::addButtonImage(1, Mainmenuitems[mainmenu == 1 ? 1 : 5], 18, 480 - 152 - 32, 128, 32);
-        Menu::addButtonImage(2, Mainmenuitems[2], 18, 480 - 228 - 32, 112, 32);
-        Menu::addButtonImage(3, Mainmenuitems[mainmenu == 1 ? 3 : 6], 18, 480 - 306 - 32, mainmenu == 1 ? 68 : 132, 32);
-        break;
-    case 3:
-        Menu::addButton( 0, "", 10 + 20, 440);
-        Menu::addButton(14, "", 10 + 400, 440);
-        Menu::addButton( 1, "", 10 + 60, 405);
-        Menu::addButton( 2, "", 10 + 70, 370);
-        Menu::addButton( 3, "", 10 + 20 - 1000, 335 - 1000);
-        Menu::addButton( 4, "", 10   , 335);
-        Menu::addButton( 5, "", 10 + 60, 300);
-        Menu::addButton( 6, "", 10 + 70, 265);
-        Menu::addButton( 9, "", 10   , 230);
-        Menu::addButton(10, "", 20   , 195);
-        Menu::addButton(11, "", 10 + 60, 160);
-        Menu::addButton(13, "", 30   , 125);
-        Menu::addButton( 7, "-Configure Controls-", 10 + 15, 90);
-        Menu::addButton(12, "-Configure Stereo -", 10 + 15, 55);
-        Menu::addButton(8, "Back", 10, 10);
-        updateSettingsMenu();
-        break;
-    case 4:
-        Menu::addButton(0, "", 10   , 400);
-        Menu::addButton(1, "", 10 + 40, 360);
-        Menu::addButton(2, "", 10 + 40, 320);
-        Menu::addButton(3, "", 10 + 30, 280);
-        Menu::addButton(4, "", 10 + 20, 240);
-        Menu::addButton(5, "", 10 + 40, 200);
-        Menu::addButton(6, "", 10 + 40, 160);
-        Menu::addButton(7, "", 10 + 30, 120);
-        Menu::addButton(8, "", 10 + 20, 80);
-        if (debugmode)
-            Menu::addButton(9, "", 10 + 10, 40);
-        Menu::addButton(debugmode ? 10 : 9, "Back", 10, 10);
-        updateControlsMenu();
-        break;
-    case 5: {
-        LoadCampaign();
-        Menu::addLabel(-1, accountactive->getName(), 5, 400);
-        Menu::addButton(1, "Tutorial", 5, 300);
-        Menu::addButton(2, "Challenge", 5, 240);
-        Menu::addButton(3, "Delete User", 400, 10);
-        Menu::addButton(4, "Main Menu", 5, 10);
-        Menu::addButton(5, "Change User", 5, 180);
-        Menu::addButton(6, "Campaign : " + accountactive->getCurrentCampaign(), 200, 420);
-
-        //show campaign map
-        //with (2,-5) offset from old code
-        Menu::addImage(-1, Mainmenuitems[7], 150 + 2, 60 - 5, 400, 400);
-        //show levels
-        int numlevels = accountactive->getCampaignChoicesMade();
-        numlevels += numlevels > 0 ? campaignlevels[numlevels - 1].nextlevel.size() : 1;
-        for (int i = 0; i < numlevels; i++) {
-            XYZ midpoint = campaignlevels[i].getCenter();
-            float itemsize = campaignlevels[i].getWidth();
-            const bool active = i >= accountactive->getCampaignChoicesMade();
-            if (!active)
-                itemsize /= 2;
-
-            if (i >= 1) {
-                XYZ start = campaignlevels[i - 1].getCenter();
-                Menu::addMapLine(start.x, start.y, midpoint.x - start.x, midpoint.y - start.y, 0.5, active ? 1 : 0.5, active ? 1 : 0.5, 0, 0);
-            }
-            Menu::addMapMarker(NB_CAMPAIGN_MENU_ITEM + i, Mapcircletexture,
-                               midpoint.x - itemsize / 2, midpoint.y - itemsize / 2, itemsize, itemsize, active ? 1 : 0.5, 0, 0);
-
-            if (active) {
-                Menu::addMapLabel(-2, campaignlevels[i].description,
-                                  campaignlevels[i].getStartX() + 10,
-                                  campaignlevels[i].getStartY() - 4);
-            }
-        }
-    }
-    break;
-    case 6:
-        Menu::addLabel(-1, "Are you sure you want to delete this user?", 10, 400);
-        Menu::addButton(1, "Yes", 10, 360);
-        Menu::addButton(2, "No", 10, 320);
-        break;
-    case 7:
-        if (Account::getNbAccounts() < 8)
-            Menu::addButton(0, "New User", 10, 400);
-        else
-            Menu::addLabel(0, "No More Users", 10, 400);
-        Menu::addLabel(-2, "", 20, 400);
-        Menu::addButton(Account::getNbAccounts() + 1, "Back", 10, 10);
-        for (int i = 0; i < Account::getNbAccounts(); i++)
-            Menu::addButton(i + 1, Account::get(i)->getName(), 10, 340 - 20 * (i + 1));
-        break;
-    case 8:
-        Menu::addButton(0, "Easier", 10, 400);
-        Menu::addButton(1, "Difficult", 10, 360);
-        Menu::addButton(2, "Insane", 10, 320);
-        break;
-    case 9:
-        for (int i = 0; i < numchallengelevels; i++) {
-            char temp[255];
-            string name = "";
-            sprintf (temp, "Level %d", i + 1);
-            for (int j = strlen(temp); j < 17; j++)
-                strcat(temp, " ");
-            name += temp;
-            sprintf (temp, "%d", (int)accountactive->getHighScore(i));
-            for (int j = strlen(temp); j < (32 - 17); j++)
-                strcat(temp, " ");
-            name += temp;
-            sprintf (temp, "%d:", (int)(((int)accountactive->getFastTime(i) - (int)(accountactive->getFastTime(i)) % 60) / 60));
-            if ((int)(accountactive->getFastTime(i)) % 60 < 10)
-                strcat(temp, "0");
-            name += temp;
-            sprintf (temp, "%d", (int)(accountactive->getFastTime(i)) % 60);
-            name += temp;
-
-            Menu::addButton(i, name, 10, 400 - i * 25, i > accountactive->getProgress() ? 0.5 : 1, 0, 0);
-        }
-
-        Menu::addButton(-1, "             High Score      Best Time", 10, 440);
-        Menu::addButton(numchallengelevels, "Back", 10, 10);
-        break;
-    case 10: {
-        Menu::addLabel(0, "Congratulations!", 220, 330);
-        Menu::addLabel(1, "You have avenged your family and", 140, 300);
-        Menu::addLabel(2, "restored peace to the island of Lugaru.", 110, 270);
-        Menu::addButton(3, "Back", 10, 10);
-        char sbuf[256];
-        sprintf(sbuf, "Your score:         %d", (int)accountactive->getCampaignScore());
-        Menu::addLabel(4, sbuf, 190, 200);
-        sprintf(sbuf, "Highest score:      %d", (int)accountactive->getCampaignHighScore());
-        Menu::addLabel(5, sbuf, 190, 180);
-    }
-    break;
-    case 18:
-        Menu::addButton(0, "", 70, 400);
-        Menu::addButton(1, "", 10, 360);
-        Menu::addButton(2, "", 40, 320);
-        Menu::addButton(3, "Back", 10, 10);
-        updateStereoConfigMenu();
-        break;
-    }
-}
-
-extern set<pair<int,int>> resolutions;
-
-void MenuTick()
-{
-    //menu buttons
-    selected = Menu::getSelected(mousecoordh * 640 / screenwidth, 480 - mousecoordv * 480 / screenheight);
-
-    // some specific case where we do something even if the left mouse button is not pressed.
-    if ((mainmenu == 5) && (endgame == 2)) {
-        accountactive->endGame();
-        endgame = 0;
-    }
-    if (mainmenu == 10)
-        endgame = 2;
-    if (mainmenu == 18 && Input::isKeyPressed(MOUSEBUTTON2) && selected == 1) {
-        stereoseparation -= 0.001;
-        updateStereoConfigMenu();
-    }
-
-    static int oldmainmenu = mainmenu;
-
-    if (Input::MouseClicked() && (selected >= 0)) { // handling of the left mouse clic in menus
-        set<pair<int,int>>::iterator newscreenresolution;
-        switch (mainmenu) {
-        case 1:
-        case 2:
-            switch (selected) {
-            case 1:
-                if (gameon) { //resume
-                    mainmenu = 0;
-                    pause_sound(stream_menutheme);
-                    resume_stream(leveltheme);
-                } else { //new game
-                    fireSound(firestartsound);
-                    flash();
-                    mainmenu = (accountactive ? 5 : 7);
-                    selected = -1;
-                }
-                break;
-            case 2: //options
-                fireSound();
-                flash();
-                mainmenu = 3;
-                if (newdetail > 2)
-                    newdetail = detail;
-                if (newdetail < 0)
-                    newdetail = detail;
-                if (newscreenwidth > 3000)
-                    newscreenwidth = screenwidth;
-                if (newscreenwidth < 0)
-                    newscreenwidth = screenwidth;
-                if (newscreenheight > 3000)
-                    newscreenheight = screenheight;
-                if (newscreenheight < 0)
-                    newscreenheight = screenheight;
-                break;
-            case 3:
-                fireSound();
-                flash();
-                if (gameon) { //end game
-                    gameon = 0;
-                    mainmenu = 1;
-                } else { //quit
-                    tryquit = 1;
-                    pause_sound(stream_menutheme);
-                }
-                break;
-            }
-            break;
-        case 3:
-            fireSound();
-            switch (selected) {
-            case 0:
-                newscreenresolution = resolutions.find(make_pair(newscreenwidth, newscreenheight));
-                /* Next one (end() + 1 is also end() so the ++ is safe even if it was not found) */
-                newscreenresolution++;
-                if (newscreenresolution == resolutions.end()) {
-                    /* It was the last one (or not found), go back to the beginning */
-                    newscreenresolution = resolutions.begin();
-                }
-                newscreenwidth  = newscreenresolution->first;
-                newscreenheight = newscreenresolution->second;
-                break;
-            case 1:
-                newdetail++;
-                if (newdetail > 2)
-                    newdetail = 0;
-                break;
-            case 2:
-                bloodtoggle++;
-                if (bloodtoggle > 2)
-                    bloodtoggle = 0;
-                break;
-            case 3:
-                difficulty++;
-                if (difficulty > 2)
-                    difficulty = 0;
-                break;
-            case 4:
-                ismotionblur = !ismotionblur;
-                break;
-            case 5:
-                decals = !decals;
-                break;
-            case 6:
-                musictoggle = !musictoggle;
-                if (musictoggle) {
-                    emit_stream_np(stream_menutheme);
-                } else {
-                    pause_sound(leveltheme);
-                    pause_sound(stream_fighttheme);
-                    pause_sound(stream_menutheme);
-
-                    for (int i = 0; i < 4; i++) {
-                        oldmusicvolume[i] = 0;
-                        musicvolume[i] = 0;
-                    }
-                }
-                break;
-            case 7: // controls
-                flash();
-                mainmenu = 4;
-                selected = -1;
-                keyselect = -1;
-                break;
-            case 8:
-                flash();
-                SaveSettings();
-                mainmenu = gameon ? 2 : 1;
-                break;
-            case 9:
-                invertmouse = !invertmouse;
-                break;
-            case 10:
-                usermousesensitivity += .2;
-                if (usermousesensitivity > 2)
-                    usermousesensitivity = .2;
-                break;
-            case 11:
-                volume += .1f;
-                if (volume > 1.0001f)
-                    volume = 0;
-                OPENAL_SetSFXMasterVolume((int)(volume * 255));
-                break;
-            case 12:
-                flash();
-                newstereomode = stereomode;
-                mainmenu = 18;
-                keyselect = -1;
-                break;
-            case 13:
-                showdamagebar = !showdamagebar;
-                break;
-            case 14:
-                toggleFullscreen();
-                break;
-            }
-            updateSettingsMenu();
-            break;
-        case 4:
-            if (!waiting) {
-                fireSound();
-                if (selected < (debugmode ? 10 : 9) && keyselect == -1)
-                    keyselect = selected;
-                if (keyselect != -1)
-                    setKeySelected();
-                if (selected == (debugmode ? 10 : 9)) {
-                    flash();
-                    mainmenu = 3;
-                }
-            }
-            updateControlsMenu();
-            break;
-        case 5:
-            fireSound();
-            flash();
-            if ((selected - NB_CAMPAIGN_MENU_ITEM >= accountactive->getCampaignChoicesMade())) {
-                startbonustotal = 0;
-
-                loading = 2;
-                loadtime = 0;
-                targetlevel = 7;
-                if (firstload)
-                    TickOnceAfter();
-                else
-                    LoadStuff();
-                whichchoice = selected - NB_CAMPAIGN_MENU_ITEM - accountactive->getCampaignChoicesMade();
-                actuallevel = (accountactive->getCampaignChoicesMade() > 0 ? campaignlevels[accountactive->getCampaignChoicesMade() - 1].nextlevel[whichchoice] : 0);
-                visibleloading = 1;
-                stillloading = 1;
-                Loadlevel(campaignlevels[actuallevel].mapname.c_str());
-                campaign = 1;
-                mainmenu = 0;
-                gameon = 1;
-                pause_sound(stream_menutheme);
-            }
-            switch (selected) {
-            case 1:
-                startbonustotal = 0;
-
-                loading = 2;
-                loadtime = 0;
-                targetlevel = -1;
-                if (firstload) {
-                    TickOnceAfter();
-                } else
-                    LoadStuff();
-                Loadlevel(-1);
-
-                mainmenu = 0;
-                gameon = 1;
-                pause_sound(stream_menutheme);
-                break;
-            case 2:
-                mainmenu = 9;
-                break;
-            case 3:
-                mainmenu = 6;
-                break;
-            case 4:
-                mainmenu = (gameon ? 2 : 1);
-                break;
-            case 5:
-                mainmenu = 7;
-                break;
-            case 6:
-                vector<string> campaigns = ListCampaigns();
-                vector<string>::iterator c;
-                if ((c = find(campaigns.begin(), campaigns.end(), accountactive->getCurrentCampaign())) == campaigns.end()) {
-                    if (!campaigns.empty())
-                        accountactive->setCurrentCampaign(campaigns.front());
-                } else {
-                    c++;
-                    if (c == campaigns.end())
-                        c = campaigns.begin();
-                    accountactive->setCurrentCampaign(*c);
-                }
-                LoadMenu();
-                break;
-            }
-            break;
-        case 6:
-            fireSound();
-            if (selected == 1) {
-                flash();
-                accountactive = Account::destroy(accountactive);
-                mainmenu = 7;
-            } else if (selected == 2) {
-                flash();
-                mainmenu = 5;
-            }
-            break;
-        case 7:
-            fireSound();
-            if (selected == 0 && Account::getNbAccounts() < 8) {
-                entername = 1;
-            } else if (selected < Account::getNbAccounts() + 1) {
-                flash();
-                mainmenu = 5;
-                accountactive = Account::get(selected - 1);
-            } else if (selected == Account::getNbAccounts() + 1) {
-                flash();
-                if (accountactive)
-                    mainmenu = 5;
-                else
-                    mainmenu = 1;
-                displaytext[0].clear();
-                displayselected = 0;
-                entername = 0;
-            }
-            break;
-        case 8:
-            fireSound();
-            flash();
-            if (selected <= 2)
-                accountactive->setDifficulty(selected);
-            mainmenu = 5;
-            break;
-        case 9:
-            if (selected < numchallengelevels && selected <= accountactive->getProgress()) {
-                fireSound();
-                flash();
-
-                startbonustotal = 0;
-
-                loading = 2;
-                loadtime = 0;
-                targetlevel = selected;
-                if (firstload)
-                    TickOnceAfter();
-                else
-                    LoadStuff();
-                Loadlevel(selected);
-                campaign = 0;
-
-                mainmenu = 0;
-                gameon = 1;
-                pause_sound(stream_menutheme);
-            }
-            if (selected == numchallengelevels) {
-                fireSound();
-                flash();
-                mainmenu = 5;
-            }
-            break;
-        case 10:
-            if (selected == 3) {
-                fireSound();
-                flash();
-                mainmenu = 5;
-            }
-            break;
-        case 18:
-            if (selected == 1)
-                stereoseparation += 0.001;
-            else {
-                fireSound();
-                if (selected == 0) {
-                    newstereomode = (StereoMode)(newstereomode + 1);
-                    while (!CanInitStereo(newstereomode)) {
-                        printf("Failed to initialize mode %s (%i)\n", StereoModeName(newstereomode), newstereomode);
-                        newstereomode = (StereoMode)(newstereomode + 1);
-                        if (newstereomode >= stereoCount)
-                            newstereomode = stereoNone;
-                    }
-                } else if (selected == 2) {
-                    stereoreverse = !stereoreverse;
-                } else if (selected == 3) {
-                    flash();
-                    mainmenu = 3;
-
-                    stereomode = newstereomode;
-                    InitStereo(stereomode);
-                }
-            }
-            updateStereoConfigMenu();
-            break;
-        }
-    }
-
-    OPENAL_SetFrequency(channels[stream_menutheme]);
-
-    if (entername) {
-        inputText(displaytext[0], &displayselected);
-        if (!waiting) { // the input as finished
-            if (!displaytext[0].empty()) { // with enter
-                accountactive = Account::add(string(displaytext[0]));
-
-                mainmenu = 8;
-
-                flash();
-
-                fireSound(firestartsound);
-
-                displaytext[0].clear();
-
-                displayselected = 0;
-            }
-            entername = 0;
-            LoadMenu();
-        }
-
-        displayblinkdelay -= multiplier;
-        if (displayblinkdelay <= 0) {
-            displayblinkdelay = .3;
-            displayblink = !displayblink;
-        }
-    }
-
-    if (entername) {
-        Menu::setText(0, displaytext[0], 20, 400, -1, -1);
-        Menu::setText(-2, displayblink ? "_" : "", 20 + displayselected * 10, 400, -1, -1);
-    }
-
-    if (oldmainmenu != mainmenu)
-        LoadMenu();
-    oldmainmenu = mainmenu;
-
-}
-
 void Game::Tick()
 {
     static XYZ facing, flatfacing;
@@ -5352,11 +4566,11 @@ void Game::Tick()
                 emit_stream_np(stream_menutheme);
                 pause_sound(leveltheme);
             }
-            LoadMenu();
+            Menu::Load();
         }
         //escape key pressed
         if (Input::isKeyPressed(SDL_SCANCODE_ESCAPE) &&
-                (gameon || mainmenu == 0 || (mainmenu >= 3 && mainmenu != 8 && !(mainmenu == 7 && entername)))) {
+                (gameon || mainmenu == 0)) {
             selected = -1;
             if (mainmenu == 0 && !winfreeze)
                 mainmenu = 2; //pause
@@ -5374,37 +4588,11 @@ void Game::Tick()
                 pause_sound(stream_menutheme);
                 resume_stream(leveltheme);
             }
-            //finished with settings menu
-            if (mainmenu == 3) {
-                SaveSettings();
-            }
-            //effects
-            if (mainmenu >= 3 && mainmenu != 8) {
-                fireSound();
-                flash();
-            }
-            //go back
-            switch (mainmenu) {
-            case 3:
-            case 5:
-                mainmenu = gameon ? 2 : 1;
-                break;
-            case 4:
-            case 18:
-                mainmenu = 3;
-                break;
-            case 6:
-            case 7:
-            case 9:
-            case 10:
-                mainmenu = 5;
-                break;
-            }
         }
     }
 
     if (mainmenu) {
-        MenuTick();
+        Menu::Tick();
     }
 
     if (!mainmenu) {
@@ -5416,14 +4604,14 @@ void Game::Tick()
             leveltime += multiplier;
 
         //keys
-        if (Input::isKeyPressed(SDL_SCANCODE_V) && debugmode) {
+        if (Input::isKeyDown(SDL_SCANCODE_LALT) && Input::isKeyPressed(SDL_SCANCODE_V) && devtools) {
             freeze = !freeze;
             if (freeze) {
                 OPENAL_SetFrequency(OPENAL_ALL);
             }
         }
 
-        if (Input::isKeyPressed(consolekey) && debugmode) {
+        if (Input::isKeyPressed(consolekey) && devtools) {
             console = !console;
             if (console) {
                 OPENAL_SetFrequency(OPENAL_ALL);
@@ -5489,7 +4677,7 @@ void Game::Tick()
                 talkdelay = 1;
             talkdelay -= multiplier;
 
-            if (talkdelay <= 0 && !Dialog::inDialog() && animation[Person::players[0]->animTarget].height != highheight) {
+            if (talkdelay <= 0 && !Dialog::inDialog() && Animation::animations[Person::players[0]->animTarget].height != highheight) {
                 for (int i = 0; i < Dialog::dialogs.size(); i++) {
                     Dialog::dialogs[i].tick(i);
                 }
@@ -5501,27 +4689,27 @@ void Game::Tick()
 
             //hotspots
             static float hotspotvisual[40];
-            if (numhotspots) {
+            if (Hotspot::hotspots.size()) {
                 XYZ hotspotsprite;
                 if (editorenabled)
-                    for (int i = 0; i < numhotspots; i++)
+                    for (int i = 0; i < Hotspot::hotspots.size(); i++)
                         hotspotvisual[i] -= multiplier / 320;
 
-                for (int i = 0; i < numhotspots; i++) {
+                for (int i = 0; i < Hotspot::hotspots.size(); i++) {
                     while (hotspotvisual[i] < 0) {
                         hotspotsprite = 0;
-                        hotspotsprite.x = float(abs(Random() % 100000)) / 100000 * hotspotsize[i];
+                        hotspotsprite.x = float(abs(Random() % 100000)) / 100000 * Hotspot::hotspots[i].size;
                         hotspotsprite = DoRotation(hotspotsprite, 0, 0, Random() % 360);
                         hotspotsprite = DoRotation(hotspotsprite, 0, Random() % 360, 0);
-                        hotspotsprite += hotspot[i];
+                        hotspotsprite += Hotspot::hotspots[i].position;
                         Sprite::MakeSprite(breathsprite, hotspotsprite, hotspotsprite * 0, 1, 0.5, 0, 7, 0.4);
-                        hotspotvisual[i] += 0.1 / hotspotsize[i] / hotspotsize[i] / hotspotsize[i];
+                        hotspotvisual[i] += 0.1 / Hotspot::hotspots[i].size / Hotspot::hotspots[i].size / Hotspot::hotspots[i].size;
                     }
                 }
 
-                for (int i = 0; i < numhotspots; i++) {
-                    if (hotspottype[i] <= 10 && hotspottype[i] > 0) {
-                        hotspot[i] = Person::players[hotspottype[i]]->coords;
+                for (int i = 0; i < Hotspot::hotspots.size(); i++) {
+                    if (Hotspot::hotspots[i].type <= 10 && Hotspot::hotspots[i].type > 0) {
+                        Hotspot::hotspots[i].position = Person::players[Hotspot::hotspots[i].type]->coords;
                     }
                 }
             }
@@ -5730,11 +4918,7 @@ void Game::Tick()
                                 if (Dialog::currentScene().sound != 0) {
                                     playdialoguescenesound();
                                     if (Dialog::currentScene().sound == -5) {
-                                        hotspot[numhotspots] = Person::players[0]->coords;
-                                        hotspotsize[numhotspots] = 10;
-                                        hotspottype[numhotspots] = -1;
-
-                                        numhotspots++;
+                                        Hotspot::hotspots.emplace_back(Person::players[0]->coords, -1, 10);
                                     }
                                     if (Dialog::currentScene().sound == -6) {
                                         hostile = 1;
@@ -5792,7 +4976,7 @@ void Game::Tick()
                 hawkcalldelay = 16 + abs(Random() % 8);
             }
 
-            doDebugKeys();
+            doDevKeys();
 
             doAttacks();
 
@@ -5818,7 +5002,7 @@ void Game::Tick()
                     (whichlevel != -2 &&
                      (Input::isKeyDown(SDL_SCANCODE_Z) &&
                       Input::isKeyDown(SDL_SCANCODE_LGUI) &&
-                      debugmode) ||
+                      devtools) ||
                      (Input::isKeyDown(jumpkey) &&
                       !respawnkeydown &&
                       !oldattackkey &&
@@ -5827,12 +5011,7 @@ void Game::Tick()
                 loading = 1;
                 leveltime = 5;
             }
-            if (!Input::isKeyDown(jumpkey))
-                respawnkeydown = 0;
-            if (Input::isKeyDown(jumpkey))
-                respawnkeydown = 1;
-
-
+            respawnkeydown = Input::isKeyDown(jumpkey);
 
 
             static bool movekey;
@@ -5844,7 +5023,7 @@ void Game::Tick()
                     oldtargetyaw = Person::players[i]->targetyaw;
                     if (i == 0 && !Dialog::inDialog()) {
                         //TODO: refactor repetitive code
-                        if (!animation[Person::players[0]->animTarget].attack &&
+                        if (!Animation::animations[Person::players[0]->animTarget].attack &&
                                 Person::players[0]->animTarget != staggerbackhighanim &&
                                 Person::players[0]->animTarget != staggerbackhardanim &&
                                 Person::players[0]->animTarget != crouchremoveknifeanim &&
@@ -5876,7 +5055,7 @@ void Game::Tick()
                         Person::players[i]->targetheadpitch = pitch;
                     }
                     if (i != 0 && Person::players[i]->aitype == playercontrolled && !Dialog::inDialog()) {
-                        if (!animation[Person::players[i]->animTarget].attack &&
+                        if (!Animation::animations[Person::players[i]->animTarget].attack &&
                                 Person::players[i]->animTarget != staggerbackhighanim &&
                                 Person::players[i]->animTarget != staggerbackhardanim &&
                                 Person::players[i]->animTarget != crouchremoveknifeanim &&
@@ -5946,7 +5125,7 @@ void Game::Tick()
 
                     doAI(i);
 
-                    if (animation[Person::players[i]->animTarget].attack == reversed) {
+                    if (Animation::animations[Person::players[i]->animTarget].attack == reversed) {
                         //Person::players[i]->targetyaw=Person::players[i]->yaw;
                         Person::players[i]->forwardkeydown = 0;
                         Person::players[i]->leftkeydown = 0;
@@ -5991,7 +5170,7 @@ void Game::Tick()
                             Person::players[i]->aitype == attacktypecutoff &&
                             !Person::players[i]->dead &&
                             !Person::players[i]->skeleton.free &&
-                            animation[Person::players[i]->animTarget].attack == neutral)
+                            Animation::animations[Person::players[i]->animTarget].attack == neutral)
                         numresponded = 1;
 
                     if (!Person::players[i]->throwkeydown)
@@ -6130,7 +5309,7 @@ void Game::Tick()
                                                                 Person::players[i]->victim->skeleton.free = 1;
                                                                 Person::players[i]->victim->skeleton.broken = 0;
 
-                                                                for (int l = 0; l < Person::players[i]->victim->skeleton.num_joints; l++) {
+                                                                for (int l = 0; l < Person::players[i]->victim->skeleton.joints.size(); l++) {
                                                                     Person::players[i]->victim->skeleton.joints[l].velchange = 0;
                                                                     Person::players[i]->victim->skeleton.joints[l].locked = 0;
                                                                 }
@@ -6319,7 +5498,7 @@ void Game::Tick()
                     }
                     movekey = 0;
                     //Do controls
-                    if (!animation[Person::players[i]->animTarget].attack &&
+                    if (!Animation::animations[Person::players[i]->animTarget].attack &&
                             Person::players[i]->animTarget != staggerbackhighanim &&
                             Person::players[i]->animTarget != staggerbackhardanim &&
                             Person::players[i]->animTarget != backhandspringanim &&
@@ -6593,7 +5772,7 @@ void Game::Tick()
                                     Person::players[i]->crouchtogglekeydown = 1;
                                 } else Person::players[i]->velocity.y = 5;
 
-                                if (mousejump && i == 0 && debugmode) {
+                                if (mousejump && i == 0 && devtools) {
                                     if (!Person::players[i]->isLanding())
                                         Person::players[i]->tempdeltav = deltav;
                                     if (Person::players[i]->tempdeltav < 0)
@@ -6618,7 +5797,7 @@ void Game::Tick()
                             if (Person::players[i]->animTarget == jumpupanim &&
                                     (((!floatjump &&
                                        !editorenabled) ||
-                                      !debugmode) ||
+                                      !devtools) ||
                                      Person::players[i]->aitype != playercontrolled)) {
                                 if (Person::players[i]->jumppower > multiplier * 6) {
                                     Person::players[i]->velocity.y += multiplier * 6;
@@ -6629,7 +5808,7 @@ void Game::Tick()
                                     Person::players[i]->jumppower = 0;
                                 }
                             }
-                            if (((floatjump || editorenabled) && debugmode) && i == 0)
+                            if (((floatjump || editorenabled) && devtools) && i == 0)
                                 Person::players[i]->velocity.y += multiplier * 30;
                         }
 
@@ -6757,7 +5936,7 @@ void Game::Tick()
                     if (distsq(&temp, &Person::players[1]->coords) >= distsq(&temp, &temp2) - 1 || distsq(&temp3, &Person::players[1]->coords) < 4) {
                         emit_sound_at(fireendsound, Person::players[1]->coords);
 
-                        for (int i = 0; i < Person::players[1]->skeleton.num_joints; i++) {
+                        for (int i = 0; i < Person::players[1]->skeleton.joints.size(); i++) {
                             if (Random() % 2 == 0) {
                                 if (!Person::players[1]->skeleton.free)
                                     temp2 = (Person::players[1]->coords - Person::players[1]->oldcoords) / multiplier / 2; //velocity/2;
@@ -6772,7 +5951,7 @@ void Game::Tick()
                         }
 
                         Person::players[1]->coords = (oldtemp + oldtemp2) / 2;
-                        for (int i = 0; i < Person::players[1]->skeleton.num_joints; i++) {
+                        for (int i = 0; i < Person::players[1]->skeleton.joints.size(); i++) {
                             Person::players[1]->skeleton.joints[i].velocity = 0;
                             if (Random() % 2 == 0) {
                                 if (!Person::players[1]->skeleton.free)
@@ -6974,23 +6153,23 @@ void Game::TickOnceAfter()
             }
         }
 
-        killhotspot = 2;
-        for (int i = 0; i < numhotspots; i++) {
-            if (hotspottype[i] > 10 && hotspottype[i] < 20) {
-                if (Person::players[hotspottype[i] - 10]->dead == 0)
-                    killhotspot = 0;
-                else if (killhotspot == 2)
-                    killhotspot = 1;
+        Hotspot::killhotspot = 2;
+        for (int i = 0; i < Hotspot::hotspots.size(); i++) {
+            if (Hotspot::hotspots[i].type > 10 && Hotspot::hotspots[i].type < 20) {
+                if (Person::players[Hotspot::hotspots[i].type - 10]->dead == 0)
+                    Hotspot::killhotspot = 0;
+                else if (Hotspot::killhotspot == 2)
+                    Hotspot::killhotspot = 1;
             }
         }
-        if (killhotspot == 2)
-            killhotspot = 0;
+        if (Hotspot::killhotspot == 2)
+            Hotspot::killhotspot = 0;
 
 
         winhotspot = false;
-        for (int i = 0; i < numhotspots; i++)
-            if (hotspottype[i] == -1)
-                if (distsq(&Person::players[0]->coords, &hotspot[i]) < hotspotsize[i])
+        for (int i = 0; i < Hotspot::hotspots.size(); i++)
+            if (Hotspot::hotspots[i].type == -1)
+                if (distsq(&Person::players[0]->coords, &Hotspot::hotspots[i].position) < Hotspot::hotspots[i].size)
                     winhotspot = true;
 
         int numalarmed = 0;
@@ -7028,7 +6207,7 @@ void Game::TickOnceAfter()
             }
 
 
-            if (killhotspot) {
+            if (Hotspot::killhotspot) {
                 changedelay = 1;
                 targetlevel = whichlevel + 1;
                 if (targetlevel > numchallengelevels - 1)
@@ -7038,10 +6217,11 @@ void Game::TickOnceAfter()
             if (changedelay > 0 && !Person::players[0]->dead && !won) {
                 //high scores, awards, win
                 if (campaign) {
-                    accountactive->winCampaignLevel(whichchoice, bonustotal, leveltime);
+                    Account::active->winCampaignLevel(whichchoice, bonustotal, leveltime);
                     scoreadded = 1;
                 } else {
-                    accountactive->winLevel(whichlevel, bonustotal - startbonustotal, leveltime);
+                    wonleveltime = leveltime;
+                    Account::active->winLevel(whichlevel, bonustotal - startbonustotal, leveltime);
                 }
                 won = 1;
             }
@@ -7054,7 +6234,7 @@ void Game::TickOnceAfter()
                 changedelay = .1;
                 alldead = false;
                 winhotspot = false;
-                killhotspot = 0;
+                Hotspot::killhotspot = 0;
             }
 
             if (!editorenabled && gameon && !mainmenu) {
@@ -7084,7 +6264,7 @@ void Game::TickOnceAfter()
 
                     fireSound(firestartsound);
 
-                    Loadlevel(campaignlevels[accountactive->getCampaignChoicesMade()].mapname.c_str());
+                    Loadlevel(campaignlevels[Account::active->getCampaignChoicesMade()].mapname.c_str());
 
                     fireSound();
 
@@ -7096,13 +6276,13 @@ void Game::TickOnceAfter()
                         (Person::players[0]->dead ||
                          (alldead && maptype == mapkilleveryone) ||
                          (winhotspot) ||
-                         (killhotspot)))
+                         (Hotspot::killhotspot)))
                     loading = 1;
                 if ((Person::players[0]->dead ||
                         (alldead && maptype == mapkilleveryone) ||
                         (winhotspot) ||
                         (windialogue) ||
-                        (killhotspot)) &&
+                        (Hotspot::killhotspot)) &&
                         changedelay <= 0) {
                     if (whichlevel != -2 && !loading && !Person::players[0]->dead) {
                         winfreeze = true;
@@ -7169,13 +6349,13 @@ void Game::TickOnceAfter()
     viewerfacing = facing;
 
     if (!cameramode) {
-        if ((animation[Person::players[0]->animTarget].attack != 3 && animation[Person::players[0]->animCurrent].attack != 3) || Person::players[0]->skeleton.free)
+        if ((Animation::animations[Person::players[0]->animTarget].attack != 3 && Animation::animations[Person::players[0]->animCurrent].attack != 3) || Person::players[0]->skeleton.free)
             target = Person::players[0]->coords + Person::players[0]->currentoffset * (1 - Person::players[0]->target) * Person::players[0]->scale + Person::players[0]->targetoffset * Person::players[0]->target * Person::players[0]->scale - Person::players[0]->facing * .05;
         else
             target = Person::players[0]->oldcoords + Person::players[0]->currentoffset * (1 - Person::players[0]->target) * Person::players[0]->scale + Person::players[0]->targetoffset * Person::players[0]->target * Person::players[0]->scale - Person::players[0]->facing * .05;
         target.y += .1;
         if (Person::players[0]->skeleton.free) {
-            for (int i = 0; i < Person::players[0]->skeleton.num_joints; i++) {
+            for (int i = 0; i < Person::players[0]->skeleton.joints.size(); i++) {
                 if (Person::players[0]->skeleton.joints[i].position.y * Person::players[0]->scale + Person::players[0]->coords.y > target.y)
                     target.y = Person::players[0]->skeleton.joints[i].position.y * Person::players[0]->scale + Person::players[0]->coords.y;
             }