]> git.jsancho.org Git - lugaru.git/blobdiff - Source/Person.cpp
Rename debug mode to dev tools
[lugaru.git] / Source / Person.cpp
index 4ccecd4cfaa70e3fc102bf9db48e5047232cf932..cada57b293cdaa13af7c2ce55179d1cd23ff92c1 100644 (file)
@@ -21,10 +21,12 @@ along with Lugaru.  If not, see <http://www.gnu.org/licenses/>.
 /**> HEADER FILES <**/
 #include "Person.h"
 #include "openal_wrapper.h"
-#include "Animation.h"
+#include "Animation/Animation.h"
 #include "Sounds.h"
 #include "Awards.h"
 #include "Game.h"
+#include "Dialog.h"
+#include "Utils/Folders.h"
 
 extern float multiplier;
 extern Terrain terrain;
@@ -53,20 +55,8 @@ extern bool decals;
 extern float fadestart;
 extern bool freeze;
 extern bool winfreeze;
-extern float flashamount, flashr, flashg, flashb;
-extern int flashdelay;
 extern bool showpoints;
 extern bool immediate;
-extern int test;
-extern bool tilt2weird;
-extern bool tiltweird;
-extern bool midweird;
-extern bool proportionweird;
-extern bool vertexweird[6];
-extern XYZ envsound[30];
-extern float envsoundvol[30];
-extern float envsoundlife[30];
-extern int numenvsounds;
 extern int tutoriallevel;
 extern float smoketex;
 extern int tutorialstage;
@@ -77,8 +67,6 @@ extern float damagedealt;
 extern int hostile;
 extern float hostiletime;
 
-extern int indialogue;
-
 extern bool gamestarted;
 
 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
@@ -86,10 +74,10 @@ std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(
 Person::Person() :
     whichpatchx(0),
     whichpatchz(0),
-    animCurrent(0),
-    animTarget(0),
+    animCurrent(bounceidleanim),
+    animTarget(bounceidleanim),
     frameCurrent(0),
-    frameTarget(0),
+    frameTarget(1),
     oldanimCurrent(0),
     oldanimTarget(0),
     oldframeCurrent(0),
@@ -105,7 +93,6 @@ Person::Person() :
     realoldcoords(),
     oldcoords(),
     coords(),
-    originalcoords(),
     velocity(),
 
     proportionhead(),
@@ -140,23 +127,20 @@ Person::Person() :
     deathbleeding(0),
     tempdeltav(0),
 
-    damagetolerance(0),
+    damagetolerance(200),
     damage(0),
     permanentdamage(0),
     superpermanentdamage(0),
     lastcollide(0),
     dead(0),
 
-    jumppower(0),
+    jumppower(5),
     onground(false),
-    madskills(0),
 
     wentforweapon(0),
 
     calcrot(false),
 
-    backwardsanim(false),
-
     facing(),
 
     bleeding(0),
@@ -203,13 +187,12 @@ Person::Person() :
 
     turnspeed(0),
 
-    aitype(0),
+    aitype(passivetype),
     aiupdatedelay(0),
     losupdatedelay(0),
     ally(0),
-    movetarget(),
     collide(0),
-    collided(0),
+    collided(-10),
     avoidcollided(0),
     loaded(false),
     whichdirection(false),
@@ -230,7 +213,7 @@ Person::Person() :
     tailmorphness(0),
     targetlefthandmorphness(0),
     targetrighthandmorphness(0),
-    targetheadmorphness(0),
+    targetheadmorphness(1),
     targetchestmorphness(0),
     targettailmorphness(0),
     lefthandmorphstart(0), lefthandmorphend(0),
@@ -242,7 +225,6 @@ Person::Person() :
     weaponmissdelay(0),
     highreversaldelay(0),
     lowreversaldelay(0),
-    nocollidedelay(0),
 
     creature(rabbittype),
 
@@ -273,22 +255,18 @@ Person::Person() :
     onfire(false),
     onfiredelay(0),
     burnt(0),
-    fireduration(0),
 
     flamedelay(0),
-    updatestuffdelay(0),
 
     playerdetail(0),
 
     num_weapons(0),
     weaponactive(-1),
-    weaponstuck(0),
+    weaponstuck(-1),
     weaponstuckwhere(0),
 
     numwaypoints(0),
     pausetime(0),
-    hastempwaypoint(false),
-    tempwaypoint(),
 
     headtarget(),
     interestdelay(0),
@@ -301,10 +279,8 @@ Person::Person() :
     lastpathfindpoint2(0),
     lastpathfindpoint3(0),
     lastpathfindpoint4(0),
-    onpath(false),
 
     waypoint(0),
-    jumppath(false),
 
     lastseen(),
     lastseentime(0),
@@ -312,6 +288,7 @@ Person::Person() :
     stunned(0),
     surprised(0),
     runninghowlong(0),
+    occluded(0),
     lastoccluded(0),
     laststanding(0),
     escapednum(0),
@@ -324,17 +301,160 @@ Person::Person() :
     whichskin(0),
     rabbitkickragdoll(false),
 
-    averageloc(),
-    oldaverageloc(),
-
     tempanimation(),
 
-    occluded(0),
-
     jumpclimb(false)
 {
 }
 
+/* Read a person in tfile. Throws an error if it’s not valid */
+Person::Person(FILE *tfile, int mapvers, unsigned i) : Person()
+{
+    id = i;
+    funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
+    if (mapvers >= 5) {
+        funpackf(tfile, "Bi", &howactive);
+    } else {
+        howactive = typeactive;
+    }
+    if (mapvers >= 3) {
+        funpackf(tfile, "Bf", &scale);
+    } else {
+        scale = -1;
+    }
+    if (mapvers >= 11) {
+        funpackf(tfile, "Bb", &immobile);
+    } else {
+        immobile = 0;
+    }
+    if (mapvers >= 12) {
+        funpackf(tfile, "Bf", &yaw);
+    } else {
+        yaw = 0;
+    }
+    targetyaw = yaw;
+    if (num_weapons < 0 || num_weapons > 5) {
+        throw InvalidPersonException();
+    }
+    if (num_weapons > 0 && num_weapons < 5) {
+        for (int j = 0; j < num_weapons; j++) {
+            weaponids[j] = weapons.size();
+            int type;
+            funpackf(tfile, "Bi", &type);
+            weapons.push_back(Weapon(type, id));
+        }
+    }
+    funpackf(tfile, "Bi", &numwaypoints);
+    for (int j = 0; j < numwaypoints; j++) {
+        funpackf(tfile, "Bf", &waypoints[j].x);
+        funpackf(tfile, "Bf", &waypoints[j].y);
+        funpackf(tfile, "Bf", &waypoints[j].z);
+        if (mapvers >= 5) {
+            funpackf(tfile, "Bi", &waypointtype[j]);
+        } else {
+            waypointtype[j] = wpkeepwalking;
+        }
+    }
+
+    funpackf(tfile, "Bi", &waypoint);
+    if (waypoint > (numwaypoints - 1)) {
+        waypoint = 0;
+    }
+
+    funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
+    funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
+    funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
+    funpackf(tfile, "Bf Bf", &power, &speedmult);
+
+    float headprop, legprop, armprop, bodyprop;
+
+    if (mapvers >= 4) {
+        funpackf(tfile, "Bf Bf Bf Bf", &headprop, &bodyprop, &armprop, &legprop);
+    } else {
+        headprop = 1;
+        bodyprop = 1;
+        armprop = 1;
+        legprop = 1;
+    }
+
+    if (creature == wolftype) {
+        proportionhead = 1.1 * headprop;
+        proportionbody = 1.1 * bodyprop;
+        proportionarms = 1.1 * armprop;
+        proportionlegs = 1.1 * legprop;
+    } else if (creature == rabbittype) {
+        proportionhead = 1.2 * headprop;
+        proportionbody = 1.05 * bodyprop;
+        proportionarms = 1.00 * armprop;
+        proportionlegs = 1.1 * legprop;
+        proportionlegs.y = 1.05 * legprop;
+    }
+
+    funpackf(tfile, "Bi", &numclothes);
+    for (int k = 0; k < numclothes; k++) {
+        int templength;
+        funpackf(tfile, "Bi", &templength);
+        for (int l = 0; l < templength; l++)
+            funpackf(tfile, "Bb", &clothes[k][l]);
+        clothes[k][templength] = '\0';
+        funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
+    }
+
+    loaded = true;
+
+    if (scale < 0) {
+        if (creature == wolftype) {
+            scale = .23;
+            damagetolerance = 300;
+        } else {
+            scale = .2;
+        }
+    }
+
+    oldcoords = coords;
+    realoldcoords = coords;
+}
+
+void Person::skeletonLoad(bool clothes)
+{
+    skeleton.id = id;
+    if (creature != wolftype) {
+        skeleton.Load(
+            "Skeleton/BasicFigure",
+            "Skeleton/BasicFigureLow",
+            "Skeleton/RabbitBelt",
+            "Models/Body.solid",
+            "Models/Body2.solid",
+            "Models/Body3.solid",
+            "Models/Body4.solid",
+            "Models/Body5.solid",
+            "Models/Body6.solid",
+            "Models/Body7.solid",
+            "Models/BodyLow.solid",
+            "Models/Belt.solid",
+            clothes
+        );
+    } else {
+        skeleton.Load(
+            "Skeleton/BasicFigureWolf",
+            "Skeleton/BasicFigureWolfLow",
+            "Skeleton/RabbitBelt",
+            "Models/Wolf.solid",
+            "Models/Wolf2.solid",
+            "Models/Wolf3.solid",
+            "Models/Wolf4.solid",
+            "Models/Wolf5.solid",
+            "Models/Wolf6.solid",
+            "Models/Wolf7.solid",
+            "Models/WolfLow.solid",
+            "Models/Belt.solid",
+            clothes
+        );
+    }
+
+    skeleton.drawmodel.textureptr.load(creatureskin[creature][whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
+}
+
 /* EFFECT
  *
  * USES:
@@ -352,7 +472,7 @@ void Person::CheckKick()
             && !victim->skeleton.free))
         return;
 
-    if (animation[victim->animTarget].height != lowheight) {
+    if (Animation::animations[victim->animTarget].height != lowheight) {
         float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
         XYZ relative = velocity;
         relative.y = 0;
@@ -363,7 +483,7 @@ void Person::CheckKick()
         if (tutoriallevel != 1)
             emit_sound_at(heavyimpactsound, victim->coords);
         victim->RagDoll(0);
-        for (int i = 0; i < victim->skeleton.num_joints; i++) {
+        for (int i = 0; i < victim->skeleton.joints.size(); i++) {
             victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
         }
         victim->Puff(neck);
@@ -403,7 +523,7 @@ void Person::CheckKick()
  *
  * USES:
  * GameTick/doPlayerCollisions - spread fire between players
- * GameTick/doDebugKeys - press f to ignite
+ * GameTick/doDevKeys - press f to ignite
  * Person::DoStuff - spread fire from lit campfires and bushes
  */
 void Person::CatchFire()
@@ -411,7 +531,7 @@ void Person::CatchFire()
     XYZ flatfacing, flatvelocity;
     int howmany;
     for (int i = 0; i < 10; i++) {
-        howmany = abs(Random() % (skeleton.num_joints));
+        howmany = abs(Random() % (skeleton.joints.size()));
         if (skeleton.free) {
             flatvelocity = skeleton.joints[howmany].velocity;
             flatfacing = skeleton.joints[howmany].position * scale + coords;
@@ -438,7 +558,7 @@ void Person::CatchFire()
  */
 int Person::getIdle()
 {
-    if (indialogue != -1 && howactive == typeactive && creature == rabbittype)
+    if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype))
         return talkidleanim;
     if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
         if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
@@ -646,17 +766,12 @@ void Person::DoBloodBig(float howmuch, int which)
             // play pain sounds
             int whichsound = -1;
 
-            // FIXME: seems to be spawning sounds by manipulating attributes... MESSY!
             if (creature == wolftype) {
                 int i = abs(Random() % 2);
                 if (i == 0)
                     whichsound = snarlsound;
                 if (i == 1)
                     whichsound = snarl2sound;
-                envsound[numenvsounds] = coords;
-                envsoundvol[numenvsounds] = 16;
-                envsoundlife[numenvsounds] = .4;
-                numenvsounds++;
             }
             if (creature == rabbittype) {
                 int i = abs(Random() % 2);
@@ -664,23 +779,16 @@ void Person::DoBloodBig(float howmuch, int which)
                     whichsound = rabbitpainsound;
                 if (i == 1 && howmuch >= 2)
                     whichsound = rabbitpain1sound;
-                envsound[numenvsounds] = coords;
-                envsoundvol[numenvsounds] = 16;
-                envsoundlife[numenvsounds] = .4;
-                numenvsounds++;
             }
 
-            if (whichsound != -1)
+            if (whichsound != -1) {
                 emit_sound_at(whichsound, coords);
+                addEnvSound(coords);
+            }
         }
 
     if (id == 0 && howmuch > 0) {
-        // FIXME: manipulating attributes
-        flashamount = .5;
-        flashr = 1;
-        flashg = 0;
-        flashb = 0;
-        flashdelay = 0;
+        Game::flash(.5, 0);
     }
 
     if (bloodtoggle && decals && tutoriallevel != 1) {
@@ -1369,7 +1477,7 @@ void Person::Reverse()
     if (aitype != playercontrolled && Random() % 10 == 0 && escapednum < 2 && difficulty == 0)
         feint = 1;
 
-    if (victim->id == 0 && animation[victim->animTarget].attack == reversal)
+    if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal)
         numreversals++;
 }
 
@@ -1423,7 +1531,7 @@ void Person::DoDamage(float howmuch)
     if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
         XYZ flatvelocity2;
         XYZ flatfacing2;
-        for (int i = 0; i < skeleton.num_joints; i++) {
+        for (int i = 0; i < skeleton.joints.size(); i++) {
             if (skeleton.free) {
                 flatvelocity2 = skeleton.joints[i].velocity;
                 flatfacing2 = skeleton.joints[i].position * scale + coords;
@@ -1462,10 +1570,6 @@ void Person::DoDamage(float howmuch)
                     whichsound = snarlsound;
                 if (i == 1)
                     whichsound = snarl2sound;
-                envsound[numenvsounds] = coords;
-                envsoundvol[numenvsounds] = 16;
-                envsoundlife[numenvsounds] = .4;
-                numenvsounds++;
             }
             if (creature == rabbittype) {
                 int i = abs(Random() % 2);
@@ -1473,14 +1577,11 @@ void Person::DoDamage(float howmuch)
                     whichsound = rabbitpainsound;
                 if (i == 1 && damage > damagetolerance)
                     whichsound = rabbitpain1sound;
-                envsound[numenvsounds] = coords;
-                envsoundvol[numenvsounds] = 16;
-                envsoundlife[numenvsounds] = .4;
-                numenvsounds++;
             }
 
             if (whichsound != -1) {
                 emit_sound_at(whichsound, coords);
+                addEnvSound(coords);
             }
         }
     speechdelay = .3;
@@ -1573,7 +1674,7 @@ void Person::DoHead()
 
         skeleton.specialforward[0] = facing;
         //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
-        for (int i = 0; i < skeleton.num_muscles; i++) {
+        for (int i = 0; i < skeleton.muscles.size(); i++) {
             if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
                 skeleton.FindRotationMuscle(i, animTarget);
             }
@@ -1619,7 +1720,7 @@ void Person::RagDoll(bool checkcollision)
         if (!isnormal(tilt)) tilt = 0;
         if (!isnormal(tilt2)) tilt2 = 0;
 
-        for (int i = 0; i < skeleton.num_joints; i++) {
+        for (int i = 0; i < skeleton.joints.size(); i++) {
             skeleton.joints[i].delay = 0;
             skeleton.joints[i].locked = 0;
             skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
@@ -1630,43 +1731,43 @@ void Person::RagDoll(bool checkcollision)
             skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
         }
 
-        for (int i = 0; i < skeleton.num_joints; i++) {
+        for (int i = 0; i < skeleton.joints.size(); i++) {
             skeleton.joints[i].velocity = 0;
             skeleton.joints[i].velchange = 0;
         }
         skeleton.DoConstraints(&coords, &scale);
-        if (animation[animCurrent].height == lowheight || animation[animTarget].height == lowheight) {
+        if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
             skeleton.DoConstraints(&coords, &scale);
             skeleton.DoConstraints(&coords, &scale);
             skeleton.DoConstraints(&coords, &scale);
             skeleton.DoConstraints(&coords, &scale);
         }
 
-        speed = animation[animTarget].speed[frameTarget] * 2;
-        if (animation[animCurrent].speed[frameCurrent] > animation[animTarget].speed[frameTarget]) {
-            speed = animation[animCurrent].speed[frameCurrent] * 2;
+        speed = targetFrame().speed * 2;
+        if (currentFrame().speed > targetFrame().speed) {
+            speed = currentFrame().speed * 2;
         }
         if (transspeed)
             speed = transspeed * 2;
 
         speed *= speedmult;
 
-        for (int i = 0; i < skeleton.num_joints; i++) {
-            if ((animation[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && animation[animCurrent].height == animation[animTarget].height)
-                skeleton.joints[i].velocity = velocity / scale + facing * 5 + DoRotation(DoRotation(DoRotation((animation[animTarget].position[i][frameTarget] - animation[animCurrent].position[i][frameCurrent]) * speed, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
+        for (int i = 0; i < skeleton.joints.size(); i++) {
+            if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height)
+                skeleton.joints[i].velocity = velocity / scale + facing * 5 + DoRotation(DoRotation(DoRotation((targetFrame().joints[i].position - currentFrame().joints[i].position) * speed, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
             else
                 skeleton.joints[i].velocity = velocity / scale + facing * 5;
             change.x = (float)(Random() % 100) / 100;
             change.y = (float)(Random() % 100) / 100;
             change.z = (float)(Random() % 100) / 100;
             skeleton.joints[i].velocity += change;
-            skeleton.joints[abs(Random() % skeleton.num_joints)].velocity -= change;
+            skeleton.joints[abs(Random() % skeleton.joints.size())].velocity -= change;
 
             change.x = (float)(Random() % 100) / 100;
             change.y = (float)(Random() % 100) / 100;
             change.z = (float)(Random() % 100) / 100;
             skeleton.joints[i].velchange += change;
-            skeleton.joints[abs(Random() % skeleton.num_joints)].velchange -= change;
+            skeleton.joints[abs(Random() % skeleton.joints.size())].velchange -= change;
         }
 
         if (checkcollision) {
@@ -1676,13 +1777,13 @@ void Person::RagDoll(bool checkcollision)
             int howmany;
             average = 0;
             howmany = 0;
-            for (j = 0; j < skeleton.num_joints; j++) {
+            for (j = 0; j < skeleton.joints.size(); j++) {
                 average += skeleton.joints[j].position;
                 howmany++;
             }
             average /= howmany;
             coords += average * scale;
-            for (j = 0; j < skeleton.num_joints; j++) {
+            for (j = 0; j < skeleton.joints.size(); j++) {
                 skeleton.joints[j].position -= average;
             }
 
@@ -1704,10 +1805,10 @@ void Person::RagDoll(bool checkcollision)
         updatedelay = 0;
 
         velocity = 0;
-        for (int i = 0; i < skeleton.num_joints; i++) {
+        for (int i = 0; i < skeleton.joints.size(); i++) {
             velocity += skeleton.joints[i].velocity * scale;
         }
-        velocity /= skeleton.num_joints;
+        velocity /= skeleton.joints.size();
 
         // drop weapon
         if (Random() % 2 == 0) {
@@ -1738,76 +1839,52 @@ void Person::RagDoll(bool checkcollision)
 
 /* EFFECT
  */
-void Person::FootLand(int which, float opacity)
+void Person::FootLand(bodypart whichfoot, float opacity)
 {
+    if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
+        cerr << "FootLand called on wrong bodypart" << endl;
+        return;
+    }
     static XYZ terrainlight;
     static XYZ footvel, footpoint;
-    if (opacity >= 1 || skiddelay <= 0)
+    if (opacity >= 1 || skiddelay <= 0) {
         if (opacity > 1) {
             footvel = 0;
-            if (which == 0)
-                footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
-            if (which == 1)
-                footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
-            //footpoint.y=coords.y;
+            footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
             if (distsq(&footpoint, &viewer))
                 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
-        } else if (environment == snowyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
+        } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
             footvel = velocity / 5;
             if (footvel.y < .8)
                 footvel.y = .8;
-            if (which == 0)
-                footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
-            if (which == 1)
-                footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
+            footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
             footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
             terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
-            if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
-                Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
-            if (opacity >= 1 || detail == 2)
-                if (detail == 2)
-                    if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
+            if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
+                if (environment == snowyenvironment) {
+                    Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
+                    if (detail == 2) {
                         terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
-        } else if (environment == grassyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
-            footvel = velocity / 5;
-            if (footvel.y < .8)
-                footvel.y = .8;
-            if (which == 0)
-                footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
-            if (which == 1)
-                footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
-            footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
-            terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
-            if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
-                Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
-        } else if (environment == desertenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
-            footvel = velocity / 5;
-            if (footvel.y < .8)
-                footvel.y = .8;
-            if (which == 0)
-                footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
-            if (which == 1)
-                footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
-            footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
-            terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
-            if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
-                Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
-            if (opacity >= 1 || detail == 2)
-                if (detail == 2)
-                    if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
+                    }
+                } else if (environment == grassyenvironment) {
+                    Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
+                } else if (environment == desertenvironment) {
+                    Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
+                    if (detail == 2) {
                         terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
-        } else if (isLanding() || animTarget == jumpupanim || isLandhard()) {
+                    }
+                }
+            }
+        } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
             footvel = velocity / 5;
             if (footvel.y < .8)
                 footvel.y = .8;
-            if (which == 0)
-                footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
-            if (which == 1)
-                footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
-            //footpoint.y=coords.y;
-            if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
+            footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
+            if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
                 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
+            }
         }
+    }
 }
 
 /* EFFECT
@@ -1845,7 +1922,7 @@ void Person::DoAnimations()
             normalsupdatedelay = 0;
 
         if (animTarget == tempanim || animCurrent == tempanim) {
-            animation[tempanim] = tempanimation;
+            Animation::animations[tempanim] = tempanimation;
         }
         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
             float gLoc[3];
@@ -1885,21 +1962,21 @@ void Person::DoAnimations()
                 numflipped++;
         }
 
-        if (animation[animTarget].attack != reversed)
+        if (Animation::animations[animTarget].attack != reversed)
             feint = 0;
         if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
             crouchtogglekeydown = 0;
             if (aitype == playercontrolled)
                 feint = 0;
         } else {
-            if (!crouchtogglekeydown && animation[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
+            if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
                 feint = 1;
             if (!isFlip())
                 crouchtogglekeydown = 1;
         }
 
 
-        if (animation[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
+        if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
             if (detail)
                 normalsupdatedelay = 0;
         }
@@ -1938,7 +2015,7 @@ void Person::DoAnimations()
                 }
             }
 
-            if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (animation[animTarget].label[frameTarget] || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
+            if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
                 if (weapons[weaponids[0]].getType() == knife) {
                     if (weaponactive == -1)
                         weaponactive = 0;
@@ -1956,39 +2033,39 @@ void Person::DoAnimations()
             }
             //Footstep sounds
             if (tutoriallevel != 1 || id == 0)
-                if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
+                if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
                     int whichsound;
                     if (onterrain) {
                         if (terrain.getOpacity(coords.x, coords.z) < .2) {
-                            if (animation[animTarget].label[frameTarget] == 1)
+                            if (targetFrame().label == 1)
                                 whichsound = footstepsound;
                             else
                                 whichsound = footstepsound2;
-                            if (animation[animTarget].label[frameTarget] == 1)
-                                FootLand(0, 1);
-                            if (animation[animTarget].label[frameTarget] == 2)
-                                FootLand(1, 1);
-                            if (animation[animTarget].label[frameTarget] == 3 && isRun()) {
-                                FootLand(1, 1);
-                                FootLand(0, 1);
+                            if (targetFrame().label == 1)
+                                FootLand(leftfoot, 1);
+                            if (targetFrame().label == 2)
+                                FootLand(rightfoot, 1);
+                            if (targetFrame().label == 3 && isRun()) {
+                                FootLand(rightfoot, 1);
+                                FootLand(leftfoot, 1);
                             }
 
                         }
                         if (terrain.getOpacity(coords.x, coords.z) >= .2) {
-                            if (animation[animTarget].label[frameTarget] == 1)
+                            if (targetFrame().label == 1)
                                 whichsound = footstepsound3;
                             else
                                 whichsound = footstepsound4;
                         }
                     }
                     if (!onterrain) {
-                        if (animation[animTarget].label[frameTarget] == 1)
+                        if (targetFrame().label == 1)
                             whichsound = footstepsound3;
                         else
                             whichsound = footstepsound4;
                     }
-                    if (animation[animTarget].label[frameTarget] == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
-                        if (animation[animTarget].attack != neutral) {
+                    if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
+                        if (Animation::animations[animTarget].attack != neutral) {
                             unsigned r = abs(Random() % 3);
                             if (r == 0)
                                 whichsound = lowwhooshsound;
@@ -1997,27 +2074,25 @@ void Person::DoAnimations()
                             if (r == 2)
                                 whichsound = highwhooshsound;
                         }
-                        if (animation[animTarget].attack == neutral)
+                        if (Animation::animations[animTarget].attack == neutral)
                             whichsound = movewhooshsound;
-                    } else if (animation[animTarget].label[frameTarget] == 4)
+                    } else if (targetFrame().label == 4)
                         whichsound = knifeswishsound;
-                    if (animation[animTarget].label[frameTarget] == 8 && tutoriallevel != 1)
+                    if (targetFrame().label == 8 && tutoriallevel != 1)
                         whichsound = landsound2;
 
                     emit_sound_at(whichsound, coords, 256.);
 
                     if (id == 0)
                         if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
-                            envsound[numenvsounds] = coords;
-                            if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim)
-                                envsoundvol[numenvsounds] = 15;
-                            else
-                                envsoundvol[numenvsounds] = 6;
-                            envsoundlife[numenvsounds] = .4;
-                            numenvsounds++;
+                            if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
+                                addEnvSound(coords, 15);
+                            } else {
+                                addEnvSound(coords, 6);
+                            }
                         }
 
-                    if (animation[animTarget].label[frameTarget] == 3) {
+                    if (targetFrame().label == 3) {
                         whichsound--;
                         emit_sound_at(whichsound, coords, 128.);
                     }
@@ -2027,10 +2102,10 @@ void Person::DoAnimations()
             if (tutoriallevel != 1 || id == 0)
                 if (speechdelay <= 0)
                     if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
-                        if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
+                        if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
                             int whichsound = -1;
-                            if (animation[animTarget].label[frameTarget] == 4 && aitype != playercontrolled) {
-                                if (animation[animTarget].attack != neutral) {
+                            if (targetFrame().label == 4 && aitype != playercontrolled) {
+                                if (Animation::animations[animTarget].attack != neutral) {
                                     unsigned r = abs(Random() % 4);
                                     if (creature == rabbittype) {
                                         if (r == 0) whichsound = rabbitattacksound;
@@ -2056,8 +2131,8 @@ void Person::DoAnimations()
 
 
             if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
-                FootLand(0, 1);
-                FootLand(1, 1);
+                FootLand(leftfoot, 1);
+                FootLand(rightfoot, 1);
             }
 
             transspeed = 0;
@@ -2066,7 +2141,7 @@ void Person::DoAnimations()
             animCurrent = animTarget;
             frameTarget++;
 
-            if (animTarget == removeknifeanim && animation[animTarget].label[frameCurrent] == 5) {
+            if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
                 for (unsigned i = 0; i < weapons.size(); i++) {
                     if (weapons[i].owner == -1)
                         if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
@@ -2081,7 +2156,7 @@ void Person::DoAnimations()
                 }
             }
 
-            if (animTarget == crouchremoveknifeanim && animation[animTarget].label[frameCurrent] == 5) {
+            if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
                 for (unsigned i = 0; i < weapons.size(); i++) {
                     bool willwork = true;
                     if (weapons[i].owner != -1)
@@ -2118,7 +2193,7 @@ void Person::DoAnimations()
                                     victim->skeleton.free = 1;
                                     victim->skeleton.broken = 0;
 
-                                    for (int j = 0; j < victim->skeleton.num_joints; j++) {
+                                    for (int j = 0; j < victim->skeleton.joints.size(); j++) {
                                         victim->skeleton.joints[j].velchange = 0;
                                         victim->skeleton.joints[j].locked = 0;
                                     }
@@ -2157,7 +2232,7 @@ void Person::DoAnimations()
                 }
             }
 
-            if (animCurrent == drawleftanim && animation[animTarget].label[frameCurrent] == 5) {
+            if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
                 if (weaponactive == -1)
                     weaponactive = 0;
                 else if (weaponactive == 0) {
@@ -2224,7 +2299,7 @@ void Person::DoAnimations()
                         }
                 }
                 if (closestid != -1)
-                    if (closestdist < 5 && !Person::players[closestid]->dead && animation[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
+                    if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
                         hasvictim = 1;
                         victim = Person::players[closestid];
                         coords = victim->coords;
@@ -2254,9 +2329,9 @@ void Person::DoAnimations()
             if (hasvictim) {
                 damagemult /= victim->damagetolerance / 200;
             }
-            if ((animation[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
-                if (animTarget == spinkickanim && animation[animTarget].label[frameCurrent] == 5) {
-                    if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
+            if ((Animation::animations[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
+                if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                    if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && Animation::animations[victim->animTarget].height != lowheight) {
                         escapednum = 0;
                         if (id == 0)
                             camerashake += .4;
@@ -2280,11 +2355,10 @@ void Person::DoAnimations()
                         relative.y = 0;
                         Normalise(&relative);
                         relative = DoRotation(relative, 0, -90, 0);
-                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
                         }
                         victim->jointVel(head) += relative * damagemult * 200;
-                        //FootLand(1,2);
                         victim->Puff(head);
                         victim->DoDamage(damagemult * 100 / victim->protectionhead);
 
@@ -2292,8 +2366,8 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == wolfslapanim && animation[animTarget].label[frameCurrent] == 5) {
-                    if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
+                if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                    if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && Animation::animations[victim->animTarget].height != lowheight) {
                         escapednum = 0;
                         if (id == 0)
                             camerashake += .4;
@@ -2316,18 +2390,17 @@ void Person::DoAnimations()
                         relative.y -= 1;
                         Normalise(&relative);
                         relative = DoRotation(relative, 0, 90, 0);
-                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                             victim->skeleton.joints[i].velocity += relative * damagemult * 20;
                         }
                         victim->jointVel(head) += relative * damagemult * 100;
-                        //FootLand(1,2);
                         victim->Puff(head);
                         victim->DoDamage(damagemult * 50 / victim->protectionhead);
                     }
                 }
 
-                if (animTarget == walljumprightkickanim && animation[animTarget].label[frameCurrent] == 5) {
-                    if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
+                if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                    if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
                         escapednum = 0;
                         if (id == 0)
                             camerashake += .4;
@@ -2347,11 +2420,10 @@ void Person::DoAnimations()
                         relative.y = 0;
                         Normalise(&relative);
                         relative = DoRotation(relative, 0, -90, 0);
-                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
                         }
                         victim->jointVel(head) += relative * damagemult * 200;
-                        //FootLand(1,2);
                         victim->Puff(head);
                         victim->DoDamage(damagemult * 150 / victim->protectionhead);
 
@@ -2362,8 +2434,8 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == walljumpleftkickanim && animation[animTarget].label[frameCurrent] == 5) {
-                    if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
+                if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                    if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
                         escapednum = 0;
                         if (id == 0)
                             camerashake += .4;
@@ -2383,11 +2455,10 @@ void Person::DoAnimations()
                         relative.y = 0;
                         Normalise(&relative);
                         relative = DoRotation(relative, 0, 90, 0);
-                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
                         }
                         victim->jointVel(head) += relative * damagemult * 200;
-                        //FootLand(1,2);
                         victim->Puff(head);
                         victim->DoDamage(damagemult * 150 / victim->protectionhead);
 
@@ -2398,8 +2469,8 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == blockhighleftstrikeanim && animation[animTarget].label[frameCurrent] == 5) {
-                    if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
+                if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                    if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
                         escapednum = 0;
                         if (id == 0)
                             camerashake += .4;
@@ -2413,17 +2484,16 @@ void Person::DoAnimations()
                         relative = victim->coords - coords;
                         relative.y = 0;
                         Normalise(&relative);
-                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                             victim->skeleton.joints[i].velocity += relative * damagemult * 30;
                         }
                         victim->jointVel(head) += relative * damagemult * 100;
-                        //FootLand(1,2);
                         victim->Puff(head);
                         victim->DoDamage(damagemult * 50 / victim->protectionhead);
                     }
                 }
 
-                if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 8) {
+                if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
                         escapednum = 0;
                         if (id == 0)
@@ -2435,7 +2505,7 @@ void Person::DoAnimations()
                         victim->skeleton.broken = 0;
                         victim->skeleton.spinny = 1;
 
-                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                             victim->skeleton.joints[i].velchange = 0;
                             victim->skeleton.joints[i].delay = 0;
                             victim->skeleton.joints[i].locked = 0;
@@ -2446,7 +2516,7 @@ void Person::DoAnimations()
                         relative = 0;
                         relative.y = 1;
                         Normalise(&relative);
-                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                             victim->skeleton.joints[i].velocity.y = relative.y * 10;
                             victim->skeleton.joints[i].position.y += relative.y * .3;
                             victim->skeleton.joints[i].oldposition.y += relative.y * .3;
@@ -2457,7 +2527,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 5) {
+                if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
                         escapednum = 0;
                         if (id == 0)
@@ -2469,7 +2539,7 @@ void Person::DoAnimations()
                         relative = victim->coords - coords;
                         relative.y = 0;
                         Normalise(&relative);
-                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                             victim->skeleton.joints[i].velocity += relative * damagemult * 90;
                         }
                         victim->Puff(abdomen);
@@ -2482,7 +2552,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == dropkickanim && animation[animTarget].label[frameCurrent] == 7) {
+                if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
                         escapednum = 0;
                         if (id == 0)
@@ -2496,7 +2566,7 @@ void Person::DoAnimations()
                         victim->skeleton.broken = 0;
                         victim->skeleton.spinny = 1;
 
-                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                             victim->skeleton.joints[i].velchange = 0;
                             //victim->skeleton.joints[i].delay=0;
                             victim->skeleton.joints[i].locked = 0;
@@ -2506,7 +2576,7 @@ void Person::DoAnimations()
                         Normalise(&relative);
                         relative.y += .3;
                         Normalise(&relative);
-                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                             victim->skeleton.joints[i].velocity += relative * damagemult * 20;
                         }
                         if (!victim->dead)
@@ -2523,7 +2593,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 5) {
+                if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
 
                     if (hasvictim)
                         if (!victim->skeleton.free)
@@ -2592,7 +2662,7 @@ void Person::DoAnimations()
                                 victim->skeleton.free = 1;
                                 victim->skeleton.broken = 0;
 
-                                for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                                for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                                     victim->skeleton.joints[i].velchange = 0;
                                     victim->skeleton.joints[i].locked = 0;
                                     //victim->skeleton.joints[i].velocity=0;
@@ -2612,7 +2682,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 6) {
+                if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
                     if (!hasvictim) {
                         emit_sound_at(knifedrawsound, coords, 128);
                     }
@@ -2682,7 +2752,7 @@ void Person::DoAnimations()
                                 victim->skeleton.free = 1;
                                 victim->skeleton.broken = 0;
 
-                                for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                                for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                                     victim->skeleton.joints[i].velchange = 0;
                                     victim->skeleton.joints[i].locked = 0;
                                     //victim->skeleton.joints[i].velocity=0;
@@ -2711,7 +2781,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == upunchanim && animation[animTarget].label[frameCurrent] == 5) {
+                if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
                         escapednum = 0;
                         if (id == 0)
@@ -2729,7 +2799,7 @@ void Person::DoAnimations()
                         relative = victim->coords - coords;
                         relative.y = 0;
                         Normalise(&relative);
-                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                             victim->skeleton.joints[i].velocity = relative * 30;
                         }
                         victim->jointVel(head) += relative * damagemult * 150;
@@ -2749,16 +2819,16 @@ void Person::DoAnimations()
                 }
 
 
-                if (animTarget == winduppunchanim && animation[animTarget].label[frameCurrent] == 5) {
+                if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
                         escapednum = 0;
                         if (id == 0)
                             camerashake += .4;
-                        if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height != lowheight) {
+                        if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
                             if (tutoriallevel != 1) {
                                 emit_sound_at(thudsound, victim->coords);
                             }
-                        } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height == lowheight) {
+                        } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
                             if (tutoriallevel != 1) {
                                 emit_sound_at(whooshhitsound, victim->coords);
                             }
@@ -2768,7 +2838,7 @@ void Person::DoAnimations()
                             }
                         }
 
-                        if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || animation[victim->animTarget].height == lowheight)
+                        if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight)
                             victim->RagDoll(0);
                         XYZ relative;
                         relative = victim->coords - coords;
@@ -2776,7 +2846,7 @@ void Person::DoAnimations()
                         Normalise(&relative);
                         relative.y = .3;
                         Normalise(&relative);
-                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                             victim->skeleton.joints[i].velocity = relative * 5;
                         }
                         victim->jointVel(abdomen) += relative * damagemult * 400;
@@ -2794,7 +2864,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == blockhighleftanim && animation[animTarget].label[frameCurrent] == 5) {
+                if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
                         if (victim->id == 0)
                             camerashake += .4;
@@ -2804,7 +2874,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == swordslashparryanim && animation[animTarget].label[frameCurrent] == 5) {
+                if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
                         if (victim->id == 0)
                             camerashake += .4;
@@ -2826,7 +2896,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == knifethrowanim && animation[animTarget].label[frameCurrent] == 5) {
+                if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
                     if (weaponactive != -1) {
                         escapednum = 0;
                         XYZ aim;
@@ -2841,9 +2911,9 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == knifeslashstartanim && animation[animTarget].label[frameCurrent] == 5) {
+                if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
                     if (hasvictim)
-                        if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*animation[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
+                        if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*Animation::animations[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
                             escapednum = 0;
                             if (tutoriallevel != 1)
                                 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
@@ -2853,7 +2923,7 @@ void Person::DoAnimations()
                                 emit_sound_at(knifeslicesound, victim->coords);
                             }
                             //victim->jointVel(abdomen)+=relative*damagemult*200;
-                            if (animation[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
+                            if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
                                 if (victim->id != 0 || difficulty == 2) {
                                     victim->frameTarget = 0;
                                     victim->animTarget = staggerbackhardanim;
@@ -2895,7 +2965,7 @@ void Person::DoAnimations()
                             victim->DoDamage(damagemult * 0);
                         }
                 }
-                if (animTarget == swordslashanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
+                if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
                         if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
                             award_bonus(id, Slashbonus);
@@ -2983,7 +3053,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == staffhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
+                if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
                         if (tutoriallevel != 1) {
                             weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
@@ -3003,12 +3073,11 @@ void Person::DoAnimations()
                         relative = DoRotation(relative, 0, 90, 0);
                         relative.y -= 1;
                         Normalise(&relative);
-                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                             victim->skeleton.joints[i].velocity += relative * damagemult * 60;
                         }
                         victim->jointVel(head) += relative * damagemult * 230;
                         victim->jointVel(neck) += relative * damagemult * 230;
-                        //FootLand(1,2);
                         victim->Puff(head);
                         if (tutoriallevel != 1) {
                             victim->DoDamage(damagemult * 120 / victim->protectionhigh);
@@ -3018,7 +3087,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == staffspinhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
+                if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
                         if (tutoriallevel != 1) {
                             weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
@@ -3036,12 +3105,11 @@ void Person::DoAnimations()
                         relative.y = 0;
                         Normalise(&relative);
                         relative = DoRotation(relative, 0, -90, 0);
-                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
                         }
                         victim->jointVel(head) += relative * damagemult * 220;
                         victim->jointVel(neck) += relative * damagemult * 220;
-                        //FootLand(1,2);
                         victim->Puff(head);
                         if (tutoriallevel != 1) {
                             victim->DoDamage(damagemult * 350 / victim->protectionhead);
@@ -3051,7 +3119,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == staffgroundsmashanim && animation[animTarget].label[frameCurrent] == 5) {
+                if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
                         escapednum = 0;
                         if (tutoriallevel != 1) {
@@ -3068,7 +3136,7 @@ void Person::DoAnimations()
                         victim->skeleton.free = 1;
                         victim->skeleton.broken = 0;
 
-                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                             victim->skeleton.joints[i].velchange = 0;
                             victim->skeleton.joints[i].locked = 0;
                             //victim->skeleton.joints[i].velocity=0;
@@ -3077,25 +3145,18 @@ void Person::DoAnimations()
                         victim->RagDoll(0);
                         XYZ relative;
                         relative = 0;
-                        /*relative=victim->coords-coords;
-                        relative.y=0;
-                        Normalise(&relative);
-                        relative=DoRotation(relative,0,90,0);*/
                         relative.y = -1;
                         Normalise(&relative);
                         if (!victim->dead) {
-                            for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                            for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                                 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
                             }
-                            //FootLand(1,2);
                             victim->jointVel(abdomen) += relative * damagemult * 40;
                         }
                         if (victim->dead) {
-                            for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                            for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                                 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
                             }
-                            //FootLand(1,2);
-                            //victim->jointVel(abdomen)+=relative*damagemult*20;
                         }
                         victim->Puff(abdomen);
                         if (tutoriallevel != 1) {
@@ -3108,8 +3169,8 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == lowkickanim && animation[animTarget].label[frameCurrent] == 5) {
-                    if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != highheight) {
+                if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                    if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
                         escapednum = 0;
                         if (id == 0)
                             camerashake += .4;
@@ -3120,13 +3181,13 @@ void Person::DoAnimations()
 
                         SolidHitBonus(id);
 
-                        if (animation[victim->animTarget].height == lowheight) {
+                        if (Animation::animations[victim->animTarget].height == lowheight) {
                             if (Random() % 2) {
                                 victim->spurt = 1;
                                 DoBlood(.2, 250);
                             }
                             victim->RagDoll(0);
-                            for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                            for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                                 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
                             }
                             victim->jointVel(head) += relative * damagemult * 200;
@@ -3145,7 +3206,7 @@ void Person::DoAnimations()
                         } else {
                             if (victim->damage >= victim->damagetolerance)
                                 victim->RagDoll(0);
-                            for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                            for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                                 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
                             }
                             victim->jointVel(abdomen) += relative * damagemult * 200;
@@ -3168,7 +3229,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == sweepanim && animation[animTarget].label[frameCurrent] == 5) {
+                if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
                     if ((victim->animTarget != jumpupanim) &&
                         (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
                         (victim != this->shared_from_this())) {
@@ -3183,15 +3244,15 @@ void Person::DoAnimations()
                         relative.y = 0;
                         Normalise(&relative);
 
-                        if (animation[victim->animTarget].height == middleheight || animation[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
+                        if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
                             victim->RagDoll(0);
 
-                            for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                            for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                                 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
                             }
                             relative = DoRotation(relative, 0, -90, 0);
                             relative.y += .1;
-                            for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                            for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                                 if (victim->skeleton.joints[i].label == leftfoot || victim->skeleton.joints[i].label == rightfoot || victim->skeleton.joints[i].label == leftankle || victim->skeleton.joints[i].label == rightankle)
                                     victim->skeleton.joints[i].velocity = relative * 80;
                             }
@@ -3201,11 +3262,11 @@ void Person::DoAnimations()
                         } else {
                             if (victim->damage >= victim->damagetolerance)
                                 victim->RagDoll(0);
-                            for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                            for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                                 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
                             }
                             relative = DoRotation(relative, 0, -90, 0);
-                            for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                            for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                                 if (victim->skeleton.joints[i].label == leftfoot || victim->skeleton.joints[i].label == rightfoot || victim->skeleton.joints[i].label == leftankle || victim->skeleton.joints[i].label == rightankle)
                                     victim->skeleton.joints[i].velocity += relative * damagemult * 80;
                             }
@@ -3226,8 +3287,8 @@ void Person::DoAnimations()
                     }
                 }
             }
-            if (animation[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
-                if (animTarget == spinkickreversalanim && animation[animTarget].label[frameCurrent] == 7) {
+            if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
+                if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
                     escapednum = 0;
                     if (id == 0)
                         camerashake += .4;
@@ -3248,19 +3309,17 @@ void Person::DoAnimations()
                     relative = victim->coords - oldcoords;
                     relative.y = 0;
                     Normalise(&relative);
-                    //relative=DoRotation(relative,0,-90,0);
-                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                    for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                         victim->skeleton.joints[i].velocity += relative * damagemult * 40;
                     }
                     victim->jointVel(abdomen) += relative * damagemult * 200;
-                    //FootLand(1,2);
                     victim->Puff(abdomen);
                     victim->DoDamage(damagemult * 150 / victim->protectionhigh);
 
                     award_bonus(id, Reversal);
                 }
 
-                if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && animation[animTarget].label[frameCurrent] == 5) {
+                if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
                     if (victim->weaponactive != -1 && victim->num_weapons > 0) {
                         if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
                             takeWeapon(victim->weaponids[victim->weaponactive]);
@@ -3273,7 +3332,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == staffhitreversalanim && animation[animTarget].label[frameCurrent] == 5) {
+                if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
                     escapednum = 0;
                     if (id == 0)
                         camerashake += .4;
@@ -3287,7 +3346,7 @@ void Person::DoAnimations()
                     relative = victim->coords - oldcoords;
                     relative.y = 0;
                     Normalise(&relative);
-                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                    for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                         victim->skeleton.joints[i].velocity += relative * damagemult * 30;
                     }
                     victim->jointVel(abdomen) += relative * damagemult * 200;
@@ -3295,7 +3354,7 @@ void Person::DoAnimations()
                     victim->DoDamage(damagemult * 70 / victim->protectionhigh);
                 }
 
-                if (animTarget == staffspinhitreversalanim && animation[animTarget].label[frameCurrent] == 7) {
+                if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
                     escapednum = 0;
                     if (id == 0)
                         camerashake += .4;
@@ -3316,7 +3375,7 @@ void Person::DoAnimations()
                     relative = victim->coords - oldcoords;
                     relative.y = 0;
                     Normalise(&relative);
-                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                    for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                         victim->skeleton.joints[i].velocity += relative * damagemult * 30;
                     }
                     victim->jointVel(abdomen) += relative * damagemult * 200;
@@ -3324,7 +3383,7 @@ void Person::DoAnimations()
                     victim->DoDamage(damagemult * 70 / victim->protectionhigh);
                 }
 
-                if (animTarget == upunchreversalanim && animation[animTarget].label[frameCurrent] == 7) {
+                if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
                     escapednum = 0;
                     victim->RagDoll(1);
                     XYZ relative;
@@ -3332,7 +3391,7 @@ void Person::DoAnimations()
                     relative.y = 0;
                     Normalise(&relative);
                     relative.y -= .1;
-                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                    for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                         victim->skeleton.joints[i].velocity += relative * damagemult * 70;
                     }
                     victim->jointVel(lefthand) *= .1;
@@ -3365,7 +3424,6 @@ void Person::DoAnimations()
                             weapons[weaponids[weaponactive]].blooddrip += 3;
                         }
                         if (weaponactive == -1 && creature == wolftype) {
-                            ;
                             emit_sound_at(clawslicesound, victim->coords, 128.);
                             victim->spurt = 1;
                             victim->DoBloodBig(2 / victim->armorhigh, 175);
@@ -3375,7 +3433,7 @@ void Person::DoAnimations()
 
 
 
-                if (animTarget == swordslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
+                if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
                     escapednum = 0;
                     victim->RagDoll(1);
                     XYZ relative;
@@ -3383,7 +3441,7 @@ void Person::DoAnimations()
                     relative.y = 0;
                     Normalise(&relative);
                     relative.y -= .1;
-                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                    for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                         victim->skeleton.joints[i].velocity += relative * damagemult * 70;
                     }
                     victim->jointVel(lefthand) *= .1 - 1;
@@ -3398,7 +3456,7 @@ void Person::DoAnimations()
                     award_bonus(id, swordreversebonus);
                 }
 
-                if (hasvictim && animTarget == knifeslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
+                if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
                     escapednum = 0;
                     if (id == 0)
                         camerashake += .4;
@@ -3415,7 +3473,7 @@ void Person::DoAnimations()
                     relative.y = 0;
                     Normalise(&relative);
                     relative = DoRotation(relative, 0, -90, 0);
-                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                    for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                         victim->skeleton.joints[i].velocity += relative * damagemult * 40;
                     }
                     victim->jointVel(abdomen) += relative * damagemult * 200;
@@ -3425,7 +3483,7 @@ void Person::DoAnimations()
                     award_bonus(id, Reversal);
                 }
 
-                if (hasvictim && animTarget == sneakattackanim && animation[animTarget].label[frameCurrent] == 7) {
+                if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
                     escapednum = 0;
                     victim->RagDoll(0);
                     victim->skeleton.spinny = 0;
@@ -3435,7 +3493,7 @@ void Person::DoAnimations()
                     Normalise(&relative);
                     if (victim->id == 0)
                         relative /= 30;
-                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                    for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                         victim->skeleton.joints[i].velocity += relative * damagemult * 40;
                     }
                     victim->damage = victim->damagetolerance;
@@ -3465,7 +3523,7 @@ void Person::DoAnimations()
                     award_bonus(id, spinecrusher);
                 }
 
-                if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
+                if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
                     if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
                         escapednum = 0;
                         if (animTarget == knifefollowanim)
@@ -3507,19 +3565,19 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 6) {
+                if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
                     escapednum = 0;
                     victim->velocity = 0;
-                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                    for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                         victim->skeleton.joints[i].velocity = 0;
                     }
                     if (animTarget == knifefollowanim) {
                         victim->RagDoll(0);
-                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                             victim->skeleton.joints[i].velocity = 0;
                         }
                     }
-                    if (weaponactive != -1 && animation[victim->animTarget].attack != reversal) {
+                    if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
                         emit_sound_at(fleshstabremovesound, victim->coords);
                         if (bloodtoggle)
                             weapons[weaponids[weaponactive]].bloody = 2;
@@ -3538,7 +3596,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (hasvictim && (animTarget == swordsneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
+                if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
                     if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
                         award_bonus(id, backstab);
 
@@ -3565,10 +3623,10 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (hasvictim && animTarget == swordsneakattackanim && animation[animTarget].label[frameCurrent] == 6) {
+                if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
                     escapednum = 0;
                     victim->velocity = 0;
-                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                    for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                         victim->skeleton.joints[i].velocity = 0;
                     }
                     if (weaponactive != -1) {
@@ -3590,7 +3648,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == sweepreversalanim && animation[animTarget].label[frameCurrent] == 7) {
+                if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
                     escapednum = 0;
                     if (id == 0)
                         camerashake += .4;
@@ -3636,7 +3694,7 @@ void Person::DoAnimations()
                     relative = DoRotation(relative, 0, 90, 0);
                     relative.y = .5;
                     Normalise(&relative);
-                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                    for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                         victim->skeleton.joints[i].velocity += relative * damagemult * 20;
                     }
                     victim->jointVel(head) += relative * damagemult * 200;
@@ -3646,7 +3704,7 @@ void Person::DoAnimations()
                     victim->velocity = 0;
                 }
 
-                if (animTarget == sweepreversalanim && ((animation[animTarget].label[frameCurrent] == 9 && victim->damage < victim->damagetolerance) || (animation[animTarget].label[frameCurrent] == 7 && victim->damage > victim->damagetolerance))) {
+                if (animTarget == sweepreversalanim && ((Animation::animations[animTarget].frames[frameCurrent].label == 9 && victim->damage < victim->damagetolerance) || (Animation::animations[animTarget].frames[frameCurrent].label == 7 && victim->damage > victim->damagetolerance))) {
                     escapednum = 0;
                     victim->RagDoll(0);
                     XYZ relative;
@@ -3656,7 +3714,7 @@ void Person::DoAnimations()
                     relative = DoRotation(relative, 0, 90, 0);
                     relative.y = .5;
                     Normalise(&relative);
-                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
+                    for (int i = 0; i < victim->skeleton.joints.size(); i++) {
                         victim->skeleton.joints[i].velocity += relative * damagemult * 20;
                     }
                     victim->jointVel(head) += relative * damagemult * 200;
@@ -3670,12 +3728,12 @@ void Person::DoAnimations()
 
 
             //Animation end
-            if (frameTarget > animation[animCurrent].numframes - 1) {
+            if (frameTarget > Animation::animations[animCurrent].frames.size() - 1) {
                 frameTarget = 0;
                 if (wasStop()) {
                     animTarget = getIdle();
-                    FootLand(0, 1);
-                    FootLand(1, 1);
+                    FootLand(leftfoot, 1);
+                    FootLand(rightfoot, 1);
                 }
                 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
                     animTarget = rollanim;
@@ -3729,8 +3787,8 @@ void Person::DoAnimations()
                 }
                 if (animCurrent == rollanim) {
                     animTarget = getCrouch();
-                    FootLand(0, 1);
-                    FootLand(1, 1);
+                    FootLand(leftfoot, 1);
+                    FootLand(rightfoot, 1);
                 }
                 if (isFlip()) {
                     if (animTarget == walljumprightkickanim) {
@@ -3893,7 +3951,7 @@ void Person::DoAnimations()
                     animTarget = getIdle();
                     lastfeint = 0;
                 }
-                if (animation[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
+                if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
                     float ycoords = oldcoords.y;
                     animTarget = getStop();
                     targetyaw += 180;
@@ -3944,7 +4002,7 @@ void Person::DoAnimations()
                     velocity.y = -5;
                     RagDoll(0);
                 }
-                if (animation[animTarget].attack == reversed) {
+                if (Animation::animations[animTarget].attack == reversed) {
                     escapednum++;
                     if (animTarget == sweepreversedanim)
                         targetyaw += 90;
@@ -3981,11 +4039,11 @@ void Person::DoAnimations()
                     oldcoords = coords;
                     coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
                     coords.y = oldcoords.y;
-                    //coords+=DoRotation(animation[animCurrent].offset,0,yaw,0)*scale;
+                    //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
                     targetoffset.y = coords.y;
                     if (onterrain)
                         targetoffset.y = terrain.getHeight(coords.x, coords.z);
-                    currentoffset = DoRotation(animation[animCurrent].offset * -1, 0, yaw, 0) * scale;
+                    currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
                     currentoffset.y -= (coords.y - targetoffset.y);
                     coords.y = targetoffset.y;
                     targetoffset = 0;
@@ -4052,10 +4110,10 @@ void Person::DoAnimations()
                     lastfeint = 0;
                 }
 
-                if (animation[animCurrent].attack == normalattack && !victim->skeleton.free && victim->animTarget != staggerbackhighanim && victim->animTarget != staggerbackhardanim && animTarget != winduppunchblockedanim && animTarget != blockhighleftanim && animTarget != swordslashparryanim && animTarget != swordslashparriedanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim) {
+                if (Animation::animations[animCurrent].attack == normalattack && !victim->skeleton.free && victim->animTarget != staggerbackhighanim && victim->animTarget != staggerbackhardanim && animTarget != winduppunchblockedanim && animTarget != blockhighleftanim && animTarget != swordslashparryanim && animTarget != swordslashparriedanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim) {
                     animTarget = getupfromfrontanim;
                     lastfeint = 0;
-                } else if (animation[animCurrent].attack == normalattack) {
+                } else if (Animation::animations[animCurrent].attack == normalattack) {
                     animTarget = getIdle();
                     lastfeint = 0;
                 }
@@ -4082,28 +4140,29 @@ void Person::DoAnimations()
         }
         if (!skeleton.free) {
             oldtarget = target;
-            if (!transspeed && animation[animTarget].attack != 2 && animation[animTarget].attack != 3) {
+            if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
                 if (!isRun() || !wasRun()) {
-                    if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
-                        target += multiplier * animation[animTarget].speed[frameTarget] * speed * 2;
-                    if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
-                        target += multiplier * animation[animCurrent].speed[frameCurrent] * speed * 2;
+                    if (targetFrame().speed > currentFrame().speed)
+                        target += multiplier * targetFrame().speed * speed * 2;
+                    if (targetFrame().speed <= currentFrame().speed)
+                        target += multiplier * currentFrame().speed * speed * 2;
                 }
                 if (isRun() && wasRun()) {
                     float tempspeed;
                     tempspeed = velspeed;
                     if (tempspeed < 10 * speedmult)
                         tempspeed = 10 * speedmult;
-                    target += multiplier * animation[animTarget].speed[frameCurrent] * speed * 1.7 * tempspeed / (speed * 45 * scale);
+                    /* FIXME - mixed of target and current here, is that intended? */
+                    target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
                 }
             } else if (transspeed)
                 target += multiplier * transspeed * speed * 2;
             else {
                 if (!isRun() || !wasRun()) {
-                    if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
-                        target += multiplier * animation[animTarget].speed[frameTarget] * 2;
-                    if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
-                        target += multiplier * animation[animCurrent].speed[frameCurrent] * 2;
+                    if (targetFrame().speed > currentFrame().speed)
+                        target += multiplier * targetFrame().speed * 2;
+                    if (targetFrame().speed <= currentFrame().speed)
+                        target += multiplier * currentFrame().speed * 2;
                 }
             }
 
@@ -4122,20 +4181,23 @@ void Person::DoAnimations()
                 oldrot = 0;
                 targetrot = 0;
             }
+            if (frameCurrent >= Animation::animations[animCurrent].frames.size()) {
+                frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
+            }
             if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
                 //Old rotates
-                for (int i = 0; i < skeleton.num_joints; i++) {
-                    skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent];
+                for (int i = 0; i < skeleton.joints.size(); i++) {
+                    skeleton.joints[i].position = currentFrame().joints[i].position;
                 }
 
                 skeleton.FindForwards();
 
-                for (int i = 0; i < skeleton.num_muscles; i++) {
+                for (int i = 0; i < skeleton.muscles.size(); i++) {
                     if (skeleton.muscles[i].visible) {
                         skeleton.FindRotationMuscle(i, animTarget);
                     }
                 }
-                for (int i = 0; i < skeleton.num_muscles; i++) {
+                for (int i = 0; i < skeleton.muscles.size(); i++) {
                     if (skeleton.muscles[i].visible) {
                         if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
                             skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
@@ -4147,18 +4209,18 @@ void Person::DoAnimations()
                 }
 
                 //New rotates
-                for (int i = 0; i < skeleton.num_joints; i++) {
-                    skeleton.joints[i].position = animation[animTarget].position[i][frameTarget];
+                for (int i = 0; i < skeleton.joints.size(); i++) {
+                    skeleton.joints[i].position = targetFrame().joints[i].position;
                 }
 
                 skeleton.FindForwards();
 
-                for (int i = 0; i < skeleton.num_muscles; i++) {
+                for (int i = 0; i < skeleton.muscles.size(); i++) {
                     if (skeleton.muscles[i].visible) {
                         skeleton.FindRotationMuscle(i, animTarget);
                     }
                 }
-                for (int i = 0; i < skeleton.num_muscles; i++) {
+                for (int i = 0; i < skeleton.muscles.size(); i++) {
                     if (skeleton.muscles[i].visible) {
                         if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
                             skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
@@ -4175,20 +4237,18 @@ void Person::DoAnimations()
                     }
                 }
             }
-            if (frameCurrent >= animation[animCurrent].numframes)
-                frameCurrent = animation[animCurrent].numframes - 1;
 
             oldanimCurrent = animCurrent;
             oldanimTarget = animTarget;
             oldframeTarget = frameTarget;
             oldframeCurrent = frameCurrent;
 
-            for (int i = 0; i < skeleton.num_joints; i++) {
-                skeleton.joints[i].velocity = (animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target) - skeleton.joints[i].position) / multiplier;
-                skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target);
+            for (int i = 0; i < skeleton.joints.size(); i++) {
+                skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target) - skeleton.joints[i].position) / multiplier;
+                skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target);
             }
             offset = currentoffset * (1 - target) + targetoffset * target;
-            for (int i = 0; i < skeleton.num_muscles; i++) {
+            for (int i = 0; i < skeleton.muscles.size(); i++) {
                 if (skeleton.muscles[i].visible) {
                     skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
                     skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
@@ -4320,7 +4380,7 @@ void Person::DoStuff()
     }
     while (flamedelay < 0 && onfire) {
         flamedelay += .006;
-        howmany = abs(Random() % (skeleton.num_joints));
+        howmany = abs(Random() % (skeleton.joints.size()));
         if (skeleton.free) {
             flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
             flatfacing = skeleton.joints[howmany].position * scale + coords;
@@ -4333,7 +4393,7 @@ void Person::DoStuff()
 
     while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
         flamedelay += .05;
-        howmany = abs(Random() % (skeleton.num_joints));
+        howmany = abs(Random() % (skeleton.joints.size()));
         if (skeleton.free) {
             flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
             flatfacing = skeleton.joints[howmany].position * scale + coords;
@@ -4400,7 +4460,7 @@ void Person::DoStuff()
         deathbleeding -= multiplier * 1.6;
         if (deathbleeding < 0)
             deathbleeding = 0;
-        if (bloodloss > damagetolerance && animation[animTarget].attack == neutral) {
+        if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
             if (weaponactive != -1) {
                 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
                 weapons[weaponids[0]].velocity.x += .01;
@@ -4416,11 +4476,7 @@ void Person::DoStuff()
                 }
 
                 if (id == 0) {
-                    flashamount = .5;
-                    flashr = 1;
-                    flashg = 0;
-                    flashb = 0;
-                    flashdelay = 0;
+                    Game::flash(.5, 0);
                 }
             }
 
@@ -4429,7 +4485,7 @@ void Person::DoStuff()
             }
             dead = 2;
             if (animTarget == knifefollowedanim && !skeleton.free) {
-                for (int i = 0; i < skeleton.num_joints; i++) {
+                for (int i = 0; i < skeleton.joints.size(); i++) {
                     skeleton.joints[i].velocity = 0;
                     skeleton.joints[i].velocity.y = -2;
                 }
@@ -4867,7 +4923,7 @@ void Person::DoStuff()
         dead = 0;
         skeleton.free = 1;
         damage -= 20;
-        for (int i = 0; i < skeleton.num_joints; i++) {
+        for (int i = 0; i < skeleton.joints.size(); i++) {
             skeleton.joints[i].velocity = 0;
         }
     }
@@ -4941,22 +4997,22 @@ void Person::DoStuff()
 
         average = 0;
         howmany = 0;
-        for (j = 0; j < skeleton.num_joints; j++) {
+        for (j = 0; j < skeleton.joints.size(); j++) {
             average += skeleton.joints[j].position;
             howmany++;
         }
         average /= howmany;
         coords += average * scale;
-        for (j = 0; j < skeleton.num_joints; j++) {
+        for (j = 0; j < skeleton.joints.size(); j++) {
             skeleton.joints[j].position -= average;
         }
         average /= multiplier;
 
         velocity = 0;
-        for (int i = 0; i < skeleton.num_joints; i++) {
+        for (int i = 0; i < skeleton.joints.size(); i++) {
             velocity += skeleton.joints[i].velocity * scale;
         }
-        velocity /= skeleton.num_joints;
+        velocity /= skeleton.joints.size();
 
         if (!isnormal(velocity.x) && velocity.x) {
             velocity = 0;
@@ -5067,9 +5123,9 @@ void Person::DoStuff()
                 frameCurrent = 0;
                 target = 0;
 
-                for (int i = 0; i < skeleton.num_joints; i++) {
-                    tempanimation.position[i][0] = skeleton.joints[i].position;
-                    tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
+                for (int i = 0; i < skeleton.joints.size(); i++) {
+                    tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
+                    tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
                 }
             }
         }
@@ -5158,9 +5214,9 @@ void Person::DoStuff()
                 if (middle.y > 0 && animTarget != rollanim)
                     targetoffset.y = middle.y + 1;
 
-                for (int i = 0; i < skeleton.num_joints; i++) {
-                    tempanimation.position[i][0] = skeleton.joints[i].position;
-                    tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
+                for (int i = 0; i < skeleton.joints.size(); i++) {
+                    tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
+                    tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
                 }
             }
         }
@@ -5250,10 +5306,7 @@ void Person::DoStuff()
                             emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
 
                             if (id == 0) {
-                                envsound[numenvsounds] = coords;
-                                envsoundvol[numenvsounds] = 4 * findLength(&velocity);
-                                envsoundlife[numenvsounds] = .4;
-                                numenvsounds++;
+                                addEnvSound(coords, 4 * findLength(&velocity));
                             }
 
                             int howmany;
@@ -5313,10 +5366,7 @@ void Person::DoStuff()
                             emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
 
                             if (id == 0) {
-                                envsound[numenvsounds] = coords;
-                                envsoundvol[numenvsounds] = 4 * findLength(&velocity);
-                                envsoundlife[numenvsounds] = .4;
-                                numenvsounds++;
+                                addEnvSound(coords, 4 * findLength(&velocity));
                             }
 
                             int howmany;
@@ -5544,7 +5594,7 @@ void Person::DoStuff()
 
         terrainnormal = terrain.getNormal(coords.x, coords.z);
 
-        if (animation[animTarget].attack != reversal) {
+        if (Animation::animations[animTarget].attack != reversal) {
             if (!isnormal(coords.x))
                 coords = oldcoords;
             oldcoords = coords;
@@ -5565,7 +5615,7 @@ void Person::DoStuff()
                 targettilt2 = 0;
         }
         onterrain = 0;
-        if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
+        if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
             targettilt2 = 0;
         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
             flatvelocity = velocity;
@@ -5594,7 +5644,7 @@ void Person::DoStuff()
         } else if (tilt2 < targettilt2) {
             tilt2 += multiplier * 400;
         }
-        if (!animation[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
+        if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
             if (tilt2 > 25)
                 tilt2 = 25;
             if (tilt2 < -25)
@@ -5661,7 +5711,7 @@ void Person::DoStuff()
             velocity = flatfacing * velspeed;
         }
 
-        if (animTarget == rollanim && animation[animTarget].label[frameTarget] != 6) {
+        if (animTarget == rollanim && targetFrame().label != 6) {
             velocity += facing * multiplier * speed * 700 * scale;
             velspeed = findLength(&velocity);
             if (velspeed > speed * 45 * scale) {
@@ -5736,7 +5786,7 @@ void Person::DoStuff()
             coords -= facing * multiplier * speed * 16 * scale;
             velocity = 0;
         }
-        if (animTarget == staggerbackhardanim && animation[staggerbackhardanim].label[frameTarget] != 6) {
+        if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
             coords -= facing * multiplier * speed * 20 * scale;
             velocity = 0;
         }
@@ -5783,7 +5833,7 @@ void Person::DoStuff()
             coords += velocity * multiplier;
 
         if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
-            if (isFlip() && animation[animTarget].label[frameTarget] == 7)
+            if (isFlip() && targetFrame().label == 7)
                 RagDoll(0);
 
             if (animTarget == jumpupanim) {
@@ -5805,10 +5855,7 @@ void Person::DoStuff()
                 emit_sound_at(landsound, coords, 128.);
 
                 if (id == 0) {
-                    envsound[numenvsounds] = coords;
-                    envsoundvol[numenvsounds] = 16;
-                    envsoundlife[numenvsounds] = .4;
-                    numenvsounds++;
+                    addEnvSound(coords);
                 }
             }
         }
@@ -5821,7 +5868,7 @@ void Person::DoStuff()
         }
 
 
-        if (isIdle() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || isStop() || animTarget == removeknifeanim || animTarget == crouchremoveknifeanim || isLanding() || isCrouch() || animation[animTarget].attack || (animTarget == rollanim && animation[animTarget].label[frameTarget] == 6)) {
+        if (isIdle() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || isStop() || animTarget == removeknifeanim || animTarget == crouchremoveknifeanim || isLanding() || isCrouch() || Animation::animations[animTarget].attack || (animTarget == rollanim && targetFrame().label == 6)) {
             velspeed = findLength(&velocity);
             velocity.y = 0;
             if (velspeed < multiplier * 300 * scale) {
@@ -5831,8 +5878,8 @@ void Person::DoStuff()
             if (velspeed > 5 && (isLanding() || isLandhard())) {
                 skiddingdelay += multiplier;
                 if (skiddelay <= 0) {
-                    FootLand(0, .5);
-                    FootLand(1, .5);
+                    FootLand(leftfoot, .5);
+                    FootLand(rightfoot, .5);
                     skiddelay = .02;
                 }
             } else
@@ -5850,8 +5897,8 @@ void Person::DoStuff()
             if (velspeed > 5 && (isLanding() || isLandhard())) {
                 skiddingdelay += multiplier;
                 if (skiddelay <= 0) {
-                    FootLand(0, .5);
-                    FootLand(1, .5);
+                    FootLand(leftfoot, .5);
+                    FootLand(rightfoot, .5);
                     skiddelay = .02;
                 }
             } else
@@ -5869,7 +5916,7 @@ void Person::DoStuff()
             }
         }
 
-        if (animation[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
+        if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
             terrainnormal = victim->coords - coords;
             Normalise(&terrainnormal);
             targetyaw = -asin(0 - terrainnormal.x);
@@ -5879,7 +5926,7 @@ void Person::DoStuff()
             targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
         }
 
-        if (animation[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
+        if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
             targetyaw = victim->targetyaw;
         }
         if (animTarget == rabbittacklinganim) {
@@ -6034,12 +6081,12 @@ int Person::DrawSkeleton()
                 }
             }
 
-            if (!skeleton.free && (!animation[animTarget].attack && animTarget != getupfrombackanim && ((animTarget != rollanim && !isFlip()) || animation[animTarget].label[frameTarget] == 6) && animTarget != getupfromfrontanim && animTarget != wolfrunninganim && animTarget != rabbitrunninganim && animTarget != backhandspringanim && animTarget != walljumpfrontanim && animTarget != hurtidleanim && !isLandhard() && !isSleeping()))
+            if (!skeleton.free && (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && ((animTarget != rollanim && !isFlip()) || targetFrame().label == 6) && animTarget != getupfromfrontanim && animTarget != wolfrunninganim && animTarget != rabbitrunninganim && animTarget != backhandspringanim && animTarget != walljumpfrontanim && animTarget != hurtidleanim && !isLandhard() && !isSleeping()))
                 DoHead();
             else {
                 targetheadyaw = -targetyaw;
                 targetheadpitch = 0;
-                if (animation[animTarget].attack == 3)
+                if (Animation::animations[animTarget].attack == 3)
                     targetheadyaw += 180;
             }
             for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
@@ -6054,12 +6101,12 @@ int Person::DrawSkeleton()
                 skeleton.drawmodelclothes.vertex[i] = 0;
                 skeleton.drawmodelclothes.vertex[i].y = 999;
             }
-            for (int i = 0; i < skeleton.num_muscles; i++) {
+            for (int i = 0; i < skeleton.muscles.size(); i++) {
                 // convenience renames
                 const int p1 = skeleton.muscles[i].parent1->label;
                 const int p2 = skeleton.muscles[i].parent2->label;
 
-                if ((skeleton.muscles[i].numvertices > 0 && playerdetail) || (skeleton.muscles[i].numverticeslow > 0 && !playerdetail)) {
+                if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
                     morphness = 0;
                     start = 0;
                     endthing = 0;
@@ -6113,7 +6160,7 @@ int Person::DrawSkeleton()
                     glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
 
                     if (playerdetail || skeleton.free == 3) {
-                        for (j = 0; j < skeleton.muscles[i].numvertices; j++) {
+                        for (j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
                             XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
                             XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
                             glMatrixMode(GL_MODELVIEW);
@@ -6142,7 +6189,7 @@ int Person::DrawSkeleton()
                         }
                     }
                     if (!playerdetail || skeleton.free == 3) {
-                        for (j = 0; j < skeleton.muscles[i].numverticeslow; j++) {
+                        for (j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
                             XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
                             glMatrixMode(GL_MODELVIEW);
                             glPushMatrix();
@@ -6172,7 +6219,7 @@ int Person::DrawSkeleton()
                     }
                     glPopMatrix();
                 }
-                if (skeleton.clothes && skeleton.muscles[i].numverticesclothes > 0) {
+                if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
                     mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
 
                     glMatrixMode(GL_MODELVIEW);
@@ -6192,7 +6239,7 @@ int Person::DrawSkeleton()
                     skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
                     glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
 
-                    for (j = 0; j < skeleton.muscles[i].numverticesclothes; j++) {
+                    for (j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
                         XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
                         glMatrixMode(GL_MODELVIEW);
                         glPushMatrix();
@@ -6301,7 +6348,6 @@ int Person::DrawSkeleton()
             if (terrainheight > 1.7)
                 terrainheight = 1.7;
 
-            //burnt=0;
             glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
             glDisable(GL_BLEND);
             glAlphaFunc(GL_GREATER, 0.0001);
@@ -6319,7 +6365,7 @@ int Person::DrawSkeleton()
                 glEnable(GL_LIGHTING);
                 glEnable(GL_BLEND);
                 if (canattack && cananger)
-                    if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
+                    if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
                         glDisable(GL_TEXTURE_2D);
                         glColor4f(1, 0, 0, 0.8);
                     }
@@ -6343,7 +6389,7 @@ int Person::DrawSkeleton()
                     skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
             }
 
-            if (!(animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed))
+            if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed))
                 if (tutoriallevel && id != 0) {
                     glPopMatrix();
                     glMatrixMode(GL_MODELVIEW);
@@ -6353,7 +6399,7 @@ int Person::DrawSkeleton()
                     glEnable(GL_LIGHTING);
                     glEnable(GL_BLEND);
                     if (canattack && cananger)
-                        if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
+                        if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
                             glDisable(GL_TEXTURE_2D);
                             glColor4f(1, 0, 0, 0.8);
                         }
@@ -6400,13 +6446,13 @@ int Person::DrawSkeleton()
                 i = weaponids[k];
                 if (weaponactive == k) {
                     if (weapons[i].getType() != staff) {
-                        for (j = 0; j < skeleton.num_muscles; j++) {
-                            if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
+                        for (j = 0; j < skeleton.muscles.size(); j++) {
+                            if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
                                 weaponattachmuscle = j;
                             }
                         }
-                        for (j = 0; j < skeleton.num_muscles; j++) {
-                            if ((skeleton.muscles[j].parent1->label == rightwrist || skeleton.muscles[j].parent2->label == rightwrist) && (skeleton.muscles[j].parent1->label != righthand && skeleton.muscles[j].parent2->label != righthand) && skeleton.muscles[j].numvertices > 0) {
+                        for (j = 0; j < skeleton.muscles.size(); j++) {
+                            if ((skeleton.muscles[j].parent1->label == rightwrist || skeleton.muscles[j].parent2->label == rightwrist) && (skeleton.muscles[j].parent1->label != righthand && skeleton.muscles[j].parent2->label != righthand) && skeleton.muscles[j].vertices.size() > 0) {
                                 weaponrotatemuscle = j;
                             }
                         }
@@ -6415,13 +6461,13 @@ int Person::DrawSkeleton()
                             weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
                     }
                     if (weapons[i].getType() == staff) {
-                        for (j = 0; j < skeleton.num_muscles; j++) {
-                            if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
+                        for (j = 0; j < skeleton.muscles.size(); j++) {
+                            if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
                                 weaponattachmuscle = j;
                             }
                         }
-                        for (j = 0; j < skeleton.num_muscles; j++) {
-                            if ((skeleton.muscles[j].parent1->label == rightelbow || skeleton.muscles[j].parent2->label == rightelbow) && (skeleton.muscles[j].parent1->label != rightshoulder && skeleton.muscles[j].parent2->label != rightshoulder) && skeleton.muscles[j].numvertices > 0) {
+                        for (j = 0; j < skeleton.muscles.size(); j++) {
+                            if ((skeleton.muscles[j].parent1->label == rightelbow || skeleton.muscles[j].parent2->label == rightelbow) && (skeleton.muscles[j].parent1->label != rightshoulder && skeleton.muscles[j].parent2->label != rightshoulder) && skeleton.muscles[j].vertices.size() > 0) {
                                 weaponrotatemuscle = j;
                             }
                         }
@@ -6444,8 +6490,8 @@ int Person::DrawSkeleton()
                         weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
                     if (weapons[i].getType() == staff)
                         weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
-                    for (j = 0; j < skeleton.num_muscles; j++) {
-                        if ((skeleton.muscles[j].parent1->label == abdomen || skeleton.muscles[j].parent2->label == abdomen) && (skeleton.muscles[j].parent1->label == neck || skeleton.muscles[j].parent2->label == neck) && skeleton.muscles[j].numvertices > 0) {
+                    for (j = 0; j < skeleton.muscles.size(); j++) {
+                        if ((skeleton.muscles[j].parent1->label == abdomen || skeleton.muscles[j].parent2->label == abdomen) && (skeleton.muscles[j].parent1->label == neck || skeleton.muscles[j].parent2->label == neck) && skeleton.muscles[j].vertices.size() > 0) {
                             weaponrotatemuscle = j;
                         }
                     }
@@ -6455,8 +6501,8 @@ int Person::DrawSkeleton()
                         weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
                     else
                         weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
-                    for (j = 0; j < skeleton.num_muscles; j++) {
-                        if ((skeleton.muscles[j].parent1->label == abdomen || skeleton.muscles[j].parent2->label == abdomen) && (skeleton.muscles[j].parent1->label == neck || skeleton.muscles[j].parent2->label == neck) && skeleton.muscles[j].numvertices > 0) {
+                    for (j = 0; j < skeleton.muscles.size(); j++) {
+                        if ((skeleton.muscles[j].parent1->label == abdomen || skeleton.muscles[j].parent2->label == abdomen) && (skeleton.muscles[j].parent1->label == neck || skeleton.muscles[j].parent2->label == neck) && skeleton.muscles[j].vertices.size() > 0) {
                             weaponrotatemuscle = j;
                         }
                     }
@@ -6490,7 +6536,7 @@ int Person::DrawSkeleton()
                             float distance;
 
                             temppoint1 = jointPos(righthand);
-                            temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
+                            temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
                             distance = findDistance(&temppoint1, &temppoint2);
                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
                             weapons[i].rotation2 *= 360 / 6.28;
@@ -6509,7 +6555,7 @@ int Person::DrawSkeleton()
                             float distance;
 
                             temppoint1 = jointPos(righthand);
-                            temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
+                            temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
                             distance = findDistance(&temppoint1, &temppoint2);
                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
                             weapons[i].rotation2 *= 360 / 6.28;
@@ -6552,8 +6598,8 @@ int Person::DrawSkeleton()
                             XYZ temppoint1, temppoint2;
                             float distance;
 
-                            temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
-                            temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
+                            temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
+                            temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
                             distance = findDistance(&temppoint1, &temppoint2);
                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
                             weapons[i].rotation2 *= 360 / 6.28;
@@ -6575,8 +6621,8 @@ int Person::DrawSkeleton()
                             XYZ temppoint1, temppoint2;
                             float distance;
 
-                            temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
-                            temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
+                            temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
+                            temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
                             distance = findDistance(&temppoint1, &temppoint2);
                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
                             weapons[i].rotation2 *= 360 / 6.28;
@@ -6620,7 +6666,7 @@ int Person::DrawSkeleton()
     calcrot = 0;
     if (skeleton.free)
         calcrot = 1;
-    if (animation[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
+    if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
         calcrot = 1;
     if (animCurrent != animTarget)
         calcrot = 1;
@@ -6682,7 +6728,7 @@ int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate,
                         if (LineFacetd(&start, &end, &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]], &model->facenormals[j], &point)) {
                             p1->y = point.y + radius;
                             if ((animTarget == jumpdownanim || isFlip())) {
-                                if (isFlip() && (frameTarget < 5 || animation[animTarget].label[frameTarget] == 7 || animation[animTarget].label[frameTarget] == 4))
+                                if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4))
                                     RagDoll(0);
 
                                 if (animTarget == jumpupanim) {
@@ -6705,10 +6751,7 @@ int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate,
                                     emit_sound_at(landsound, coords, 128.);
 
                                     if (id == 0) {
-                                        envsound[numenvsounds] = coords;
-                                        envsoundvol[numenvsounds] = 16;
-                                        envsoundlife[numenvsounds] = .4;
-                                        numenvsounds++;
+                                        addEnvSound(coords);
                                     }
                                 }
                             }
@@ -6798,13 +6841,13 @@ void Person::addClothes()
 bool Person::addClothes(const int& clothesId)
 {
     LOGFUNC;
-    const char* fileName = clothes[clothesId];
+    const std::string fileName = clothes[clothesId];
 
     GLubyte* array = &skeleton.skinText[0];
 
     //Load Image
     ImageRec texture;
-    bool opened = load_image(fileName, texture);
+    bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
 
     float alphanum;
     //Is it valid?