]> git.jsancho.org Git - lugaru.git/blobdiff - Source/Person.cpp
Moved as much as possible init in Person constructor
[lugaru.git] / Source / Person.cpp
index de7ace0f242f2a6244aa13d50a184f7dbdfd436a..3729c4f6ebc3c31895da0956a59698b398cb1413 100644 (file)
@@ -1,22 +1,21 @@
 /*
 Copyright (C) 2003, 2010 - Wolfire Games
+Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
 
 This file is part of Lugaru.
 
-Lugaru is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
+Lugaru is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
+Lugaru is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+along with Lugaru.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 /**> HEADER FILES <**/
@@ -26,6 +25,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "Sounds.h"
 #include "Awards.h"
 #include "Game.h"
+#include "Dialog.h"
+#include "Utils/Folders.h"
 
 extern float multiplier;
 extern Terrain terrain;
@@ -44,7 +45,6 @@ extern GLubyte bloodText[512 * 512 * 3];
 extern GLubyte wolfbloodText[512 * 512 * 3];
 extern int bloodtoggle;
 extern Objects objects;
-extern bool osx;
 extern bool autoslomo;
 extern float camerashake;
 extern float woozy;
@@ -55,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;
@@ -79,22 +67,369 @@ extern float damagedealt;
 extern int hostile;
 extern float hostiletime;
 
-extern int indialogue;
-
 extern bool gamestarted;
 
-Person player[maxplayers];
+std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
+
+Person::Person() :
+    whichpatchx(0),
+    whichpatchz(0),
+    animCurrent(bounceidleanim),
+    animTarget(bounceidleanim),
+    frameCurrent(0),
+    frameTarget(1),
+    oldanimCurrent(0),
+    oldanimTarget(0),
+    oldframeCurrent(0),
+    oldframeTarget(0),
+    howactive(typeactive),
+    parriedrecently(0),
+    superruntoggle(false),
+    lastattack(0), lastattack2(0), lastattack3(0),
+    currentoffset(), targetoffset(), offset(),
+    target(0),
+    transspeed(0),
+
+    realoldcoords(),
+    oldcoords(),
+    coords(),
+    velocity(),
+
+    proportionhead(),
+    proportionlegs(),
+    proportionarms(),
+    proportionbody(),
+
+    unconscioustime(0),
+
+    immobile(false),
+
+    velspeed(0),
+    targetyaw(0),
+    targetrot(0),
+    rot(0),
+    oldrot(0),
+    lookyaw(0),
+    lookpitch(0),
+    yaw(0),
+    pitch(0),
+    lowyaw(0),
+    tilt(0),
+    targettilt(0),
+    tilt2(0),
+    targettilt2(0),
+    rabbitkickenabled(false),
+
+    bloodloss(0),
+    bleeddelay(0),
+    skiddelay(0),
+    skiddingdelay(0),
+    deathbleeding(0),
+    tempdeltav(0),
+
+    damagetolerance(200),
+    damage(0),
+    permanentdamage(0),
+    superpermanentdamage(0),
+    lastcollide(0),
+    dead(0),
+
+    jumppower(5),
+    onground(false),
+
+    wentforweapon(0),
+
+    calcrot(false),
+
+    facing(),
+
+    bleeding(0),
+    bleedx(0), bleedy(0),
+    direction(0),
+    texupdatedelay(0),
+
+    headyaw(0), headpitch(0),
+    targetheadyaw(0), targetheadpitch(0),
+
+    onterrain(false),
+    pause(false),
+
+    grabdelay(0),
+
+    victim(nullptr),
+    hasvictim(false),
+
+    updatedelay(0),
+    normalsupdatedelay(0),
+
+    jumpstart(false),
+    forwardkeydown(false),
+    forwardstogglekeydown(false),
+    rightkeydown(false),
+    leftkeydown(false),
+    backkeydown(false),
+    jumpkeydown(false),
+    jumptogglekeydown(false),
+    crouchkeydown(false),
+    crouchtogglekeydown(false),
+    drawkeydown(false),
+    drawtogglekeydown(false),
+    throwkeydown(false),
+    throwtogglekeydown(false),
+    attackkeydown(false),
+    feint(false),
+    lastfeint(false),
+    headless(false),
+
+    crouchkeydowntime(0),
+    jumpkeydowntime(0),
+    freefall(false),
+
+    turnspeed(0),
+
+    aitype(passivetype),
+    aiupdatedelay(0),
+    losupdatedelay(0),
+    ally(0),
+    collide(0),
+    collided(-10),
+    avoidcollided(0),
+    loaded(false),
+    whichdirection(false),
+    whichdirectiondelay(0),
+    avoidsomething(false),
+    avoidwhere(),
+    blooddimamount(0),
+
+    staggerdelay(0),
+    blinkdelay(0),
+    twitchdelay(0),
+    twitchdelay2(0),
+    twitchdelay3(0),
+    lefthandmorphness(0),
+    righthandmorphness(0),
+    headmorphness(0),
+    chestmorphness(0),
+    tailmorphness(0),
+    targetlefthandmorphness(0),
+    targetrighthandmorphness(0),
+    targetheadmorphness(1),
+    targetchestmorphness(0),
+    targettailmorphness(0),
+    lefthandmorphstart(0), lefthandmorphend(0),
+    righthandmorphstart(0), righthandmorphend(0),
+    headmorphstart(0), headmorphend(0),
+    chestmorphstart(0), chestmorphend(0),
+    tailmorphstart(0), tailmorphend(0),
+
+    weaponmissdelay(0),
+    highreversaldelay(0),
+    lowreversaldelay(0),
+
+    creature(rabbittype),
+
+    id(0),
+
+    skeleton(),
+
+    speed(0),
+    scale(-1),
+    power(0),
+    speedmult(0),
+
+    protectionhead(0),
+    protectionhigh(0),
+    protectionlow(0),
+    armorhead(0),
+    armorhigh(0),
+    armorlow(0),
+    metalhead(false),
+    metalhigh(false),
+    metallow(false),
+
+    numclothes(0),
+
+    landhard(false),
+    bled(false),
+    spurt(false),
+    onfire(false),
+    onfiredelay(0),
+    burnt(0),
+
+    flamedelay(0),
+
+    playerdetail(0),
+
+    num_weapons(0),
+    weaponactive(-1),
+    weaponstuck(-1),
+    weaponstuckwhere(0),
+
+    numwaypoints(0),
+    pausetime(0),
+
+    headtarget(),
+    interestdelay(0),
+
+    finalfinaltarget(),
+    finaltarget(),
+    finalpathfindpoint(0),
+    targetpathfindpoint(0),
+    lastpathfindpoint(0),
+    lastpathfindpoint2(0),
+    lastpathfindpoint3(0),
+    lastpathfindpoint4(0),
+
+    waypoint(0),
+
+    lastseen(),
+    lastseentime(0),
+    lastchecktime(0),
+    stunned(0),
+    surprised(0),
+    runninghowlong(0),
+    occluded(0),
+    lastoccluded(0),
+    laststanding(0),
+    escapednum(0),
+
+    speechdelay(0),
+    neckspurtdelay(0),
+    neckspurtparticledelay(0),
+    neckspurtamount(0),
+
+    whichskin(0),
+    rabbitkickragdoll(false),
+
+    tempanimation(),
+
+    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;
+}
 
+/* EFFECT
+ *
+ * USES:
+ * GameTick/doPlayerCollisions
+ */
 void Person::CheckKick()
 {
     if (!(hasvictim
             && (animTarget == rabbitkickanim
                 && victim
-                && victim != this
+                && victim != this->shared_from_this()
                 && frameCurrent >= 2
                 && animCurrent == rabbitkickanim)
-            && (distsq(&coords, &victim->coords) < 1.2)
-            && (!victim->skeleton.free)))
+            && distsq(&coords, &victim->coords) < 1.2
+            && !victim->skeleton.free))
         return;
 
     if (animation[victim->animTarget].height != lowheight) {
@@ -113,7 +448,8 @@ void Person::CheckKick()
         }
         victim->Puff(neck);
         victim->DoDamage(100 * damagemult / victim->protectionhigh);
-        if (id == 0)camerashake += .4;
+        if (id == 0)
+            camerashake += .4;
 
         target = 0;
         frameCurrent = 3;
@@ -139,20 +475,30 @@ void Person::CheckKick()
         victim->oldcoords = victim->coords;
         coords = victim->coords;
         victim->targetyaw = targetyaw;
-        victim->victim = this;
+        victim->victim = this->shared_from_this();
     }
 }
 
+/* EFFECT
+ *
+ * USES:
+ * GameTick/doPlayerCollisions - spread fire between players
+ * GameTick/doDebugKeys - press f to ignite
+ * Person::DoStuff - spread fire from lit campfires and bushes
+ */
 void Person::CatchFire()
 {
     XYZ flatfacing, flatvelocity;
     int howmany;
     for (int i = 0; i < 10; i++) {
         howmany = abs(Random() % (skeleton.num_joints));
-        if (!skeleton.free)flatvelocity = velocity;
-        if (skeleton.free)flatvelocity = skeleton.joints[howmany].velocity;
-        if (!skeleton.free)flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
-        if (skeleton.free)flatfacing = skeleton.joints[howmany].position * scale + coords;
+        if (skeleton.free) {
+            flatvelocity = skeleton.joints[howmany].velocity;
+            flatfacing = skeleton.joints[howmany].position * scale + coords;
+        } else {
+            flatvelocity = velocity;
+            flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
+        }
         Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
     }
 
@@ -167,13 +513,22 @@ void Person::CatchFire()
     onfire = 1;
 }
 
+/* FUNCTION
+ * idle animation for this creature (depending on status)
+ */
 int Person::getIdle()
 {
-    if (indialogue != -1 && howactive == typeactive && creature == rabbittype)return talkidleanim;
-    if (hasvictim && victim != this/*||(id==0&&attackkeydown)*/)if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype && victim->aitype != searchtype && aitype != passivetype && aitype != searchtype && victim->id < numplayers)) {
+    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 &&
+            victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
+            victim->id < Person::players.size())) {
             if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
-                if (creature == rabbittype)return fightidleanim;
-                if (creature == wolftype)return wolfidle;
+                if (creature == rabbittype)
+                    return fightidleanim;
+                if (creature == wolftype)
+                    return wolfidle;
             }
             if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
                 if (weapons[weaponids[weaponactive]].getType() == knife)
@@ -185,59 +540,90 @@ int Person::getIdle()
                 if (weapons[weaponids[weaponactive]].getType() == staff)
                     return swordfightidleanim;
             }
-            if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)return fightsidestep;
-        }
-    if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)return hurtidleanim;
-    if (howactive == typesitting)return sitanim;
-    if (howactive == typesittingwall)return sitwallanim;
-    if (howactive == typesleeping)return sleepanim;
-    if (howactive == typedead1)return dead1anim;
-    if (howactive == typedead2)return dead2anim;
-    if (howactive == typedead3)return dead3anim;
-    if (howactive == typedead4)return dead4anim;
-    if (creature == rabbittype)return bounceidleanim;
-    if (creature == wolftype)return wolfidle;
+            if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
+                return fightsidestep;
+        }
+    if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
+        return hurtidleanim;
+    if (howactive == typesitting) return sitanim;
+    if (howactive == typesittingwall) return sitwallanim;
+    if (howactive == typesleeping) return sleepanim;
+    if (howactive == typedead1) return dead1anim;
+    if (howactive == typedead2) return dead2anim;
+    if (howactive == typedead3) return dead3anim;
+    if (howactive == typedead4) return dead4anim;
+    if (creature == rabbittype) return bounceidleanim;
+    if (creature == wolftype) return wolfidle;
     return 0;
 }
 
+/* FUNCTION
+ * crouch animation for this creature
+ */
 int Person::getCrouch()
 {
-    if (creature == rabbittype)return crouchanim;
-    if (creature == wolftype)return wolfcrouchanim;
+    if (creature == rabbittype)
+        return crouchanim;
+    if (creature == wolftype)
+        return wolfcrouchanim;
     return 0;
 }
 
+/* FUNCTION
+ * running animation for this creature (can be upright or all fours)
+ */
 int Person::getRun()
 {
-    if (creature == rabbittype && (!superruntoggle || weaponactive != -1))return runanim;
-    if (creature == wolftype && (!superruntoggle))return wolfrunanim;
-
-    if (creature == rabbittype && (superruntoggle && weaponactive == -1))return rabbitrunninganim;
-    if (creature == wolftype && (superruntoggle))return wolfrunninganim;
+    if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
+        return runanim;
+    if (creature == wolftype && (!superruntoggle))
+        return wolfrunanim;
+
+    if (creature == rabbittype && (superruntoggle && weaponactive == -1))
+        return rabbitrunninganim;
+    if (creature == wolftype && (superruntoggle))
+        return wolfrunninganim;
     return 0;
 }
 
+/* FUNCTION
+ */
 int Person::getStop()
 {
-    if (creature == rabbittype)return stopanim;
-    if (creature == wolftype)return wolfstopanim;
+    if (creature == rabbittype)
+        return stopanim;
+    if (creature == wolftype)
+        return wolfstopanim;
     return 0;
 }
 
+/* FUNCTION
+ */
 int Person::getLanding()
 {
-    if (creature == rabbittype)return landanim;
-    if (creature == wolftype)return wolflandanim;
+    if (creature == rabbittype)
+        return landanim;
+    if (creature == wolftype)
+        return wolflandanim;
     return 0;
 }
 
+/* FUNCTION
+ */
 int Person::getLandhard()
 {
-    if (creature == rabbittype)return landhardanim;
-    if (creature == wolftype)return wolflandhardanim;
+    if (creature == rabbittype)
+        return landhardanim;
+    if (creature == wolftype)
+        return wolflandhardanim;
     return 0;
 }
 
+/* EFFECT
+ *
+ * USES:
+ * Person::DoAnimations
+ */
 static void
 SolidHitBonus(int playerid)
 {
@@ -247,41 +633,41 @@ SolidHitBonus(int playerid)
         award_bonus(playerid, solidhit);
 }
 
+/* EFFECT
+ * spawns blood effects
+ */
 void Person::DoBlood(float howmuch, int which)
 {
+    // FIXME: should abstract out inputs
     static int bleedxint, bleedyint;
     static XYZ bloodvel;
-    //if(howmuch&&id==0)blooddimamount=1;
     if (bloodtoggle && tutoriallevel != 1) {
         if (bleeding <= 0 && spurt) {
             spurt = 0;
             for (int i = 0; i < 3; i++) {
+                // emit blood particles
                 bloodvel = 0;
-                if (!skeleton.free) {
-                    bloodvel.z = 10;
-                    bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
-                }
                 if (skeleton.free) {
                     bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
-                }
-                if (skeleton.free)bloodvel += DoRotation(skeleton.joints[skeleton.jointlabels[head]].velocity, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
-                if (!skeleton.free)bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
-                if (skeleton.free) {
-                    Sprite::MakeSprite(bloodsprite, skeleton.joints[skeleton.jointlabels[head]].position * scale + coords, bloodvel, 1, 1, 1, .05, 1);
-                    Sprite::MakeSprite(bloodflamesprite, skeleton.joints[skeleton.jointlabels[head]].position * scale + coords, bloodvel, 1, 1, 1, .3, 1);
-                }
-                if (!skeleton.free) {
-                    Sprite::MakeSprite(bloodsprite, DoRotation((skeleton.joints[skeleton.jointlabels[head]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
-                    Sprite::MakeSprite(bloodflamesprite, DoRotation((skeleton.joints[skeleton.jointlabels[head]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
+                    bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
+                    Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
+                    Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
+                } else {
+                    bloodvel.z = 10;
+                    bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
+                    bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
+                    Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
+                    Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
                 }
             }
-            if (Random() % 2 == 0)
+            if (Random() % 2 == 0) // 50% chance
                 for (int i = 0; i < 3; i++) {
                     if (Random() % 2 != 0) {
+                        // emit teeth particles
                         bloodvel = 0;
                         if (skeleton.free) {
                             bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
-                            bloodvel += DoRotation(skeleton.joints[skeleton.jointlabels[head]].velocity, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
+                            bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
                         } else {
                             bloodvel.z = 10;
                             bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
@@ -289,15 +675,16 @@ void Person::DoBlood(float howmuch, int which)
                         }
                         bloodvel *= .2;
                         if (skeleton.free) {
-                            Sprite::MakeSprite(splintersprite, skeleton.joints[skeleton.jointlabels[head]].position * scale + coords, bloodvel, 1, 1, 1, .05, 1);
+                            Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
                         } else {
-                            Sprite::MakeSprite(splintersprite, DoRotation((skeleton.joints[skeleton.jointlabels[head]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
+                            Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
                         }
-                        Sprite::setLastSpriteSpecial(3);
+                        Sprite::setLastSpriteSpecial(3); // sets it to teeth
                     }
                 }
         }
         if (decals) {
+            // FIXME: manipulating attributes
             bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
             bleedxint = 0;
             bleedyint = 0;
@@ -319,75 +706,77 @@ void Person::DoBlood(float howmuch, int which)
         }
 
     }
-    if (bleeding > 2)bleeding = 2;
+    if (bleeding > 2)
+        bleeding = 2;
 }
 
+/* EFFECT
+ * spawns big blood effects and ???
+ * modifies character's skin texture
+ */
 void Person::DoBloodBig(float howmuch, int which)
 {
     static int bleedxint, bleedyint, i, j;
     static XYZ bloodvel;
-    if (howmuch && id == 0)blooddimamount = 1;
+    if (howmuch && id == 0)
+        blooddimamount = 1;
 
     if (tutoriallevel != 1 || id == 0)
         if (aitype != playercontrolled && howmuch > 0) {
+            // play pain sounds
             int whichsound = -1;
 
             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 (i == 0)
+                    whichsound = snarlsound;
+                if (i == 1)
+                    whichsound = snarl2sound;
             }
             if (creature == rabbittype) {
                 int i = abs(Random() % 2);
-                if (i == 0)whichsound = rabbitpainsound;
-                if (i == 1 && howmuch >= 2)whichsound = rabbitpain1sound;
-                envsound[numenvsounds] = coords;
-                envsoundvol[numenvsounds] = 16;
-                envsoundlife[numenvsounds] = .4;
-                numenvsounds++;
-                //if(i==2)whichsound=rabbitpain2sound;
+                if (i == 0)
+                    whichsound = rabbitpainsound;
+                if (i == 1 && howmuch >= 2)
+                    whichsound = rabbitpain1sound;
             }
 
-            if (whichsound != -1)
+            if (whichsound != -1) {
                 emit_sound_at(whichsound, coords);
+                addEnvSound(coords);
+            }
         }
 
     if (id == 0 && howmuch > 0) {
-        flashamount = .5;
-        flashr = 1;
-        flashg = 0;
-        flashb = 0;
-        flashdelay = 0;
+        Game::flash(.5, 0);
     }
 
     if (bloodtoggle && decals && tutoriallevel != 1) {
         if (bleeding <= 0 && spurt) {
             spurt = 0;
             for (int i = 0; i < 3; i++) {
+                // emit blood particles
+                // FIXME: copypaste from above
                 bloodvel = 0;
-                if (!skeleton.free) {
-                    bloodvel.z = 10;
-                    bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
-                }
                 if (skeleton.free) {
                     bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
-                }
-                if (skeleton.free)bloodvel += DoRotation(skeleton.joints[skeleton.jointlabels[head]].velocity, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
-                if (!skeleton.free)bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
-                if (skeleton.free) {
-                    Sprite::MakeSprite(bloodsprite, skeleton.joints[skeleton.jointlabels[head]].position * scale + coords, bloodvel, 1, 1, 1, .05, 1);
-                    Sprite::MakeSprite(bloodflamesprite, skeleton.joints[skeleton.jointlabels[head]].position * scale + coords, bloodvel, 1, 1, 1, .3, 1);
-                }
-                if (!skeleton.free) {
-                    Sprite::MakeSprite(bloodsprite, DoRotation((skeleton.joints[skeleton.jointlabels[head]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
-                    Sprite::MakeSprite(bloodflamesprite, DoRotation((skeleton.joints[skeleton.jointlabels[head]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
+                    bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
+                    Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
+                    Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
+                } else {
+                    bloodvel.z = 10;
+                    bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
+                    bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
+                    Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
+                    Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
                 }
             }
         }
+
+        // weird texture manipulation code follows.
+        // looks like this is painting blood onto the character's skin texture
+        // FIXME: surely there's a better way
+
         int offsetx = 0, offsety = 0;
         if (which == 225) {
             offsety = Random() % 40;
@@ -419,10 +808,10 @@ void Person::DoBloodBig(float howmuch, int which)
             for (i = 0; i < 512; i++) {
                 for (j = 0; j < 512; j++) {
                     if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
-                        if (i < startx)startx = i;
-                        if (j < starty)starty = j;
-                        if (i > endx)endx = i;
-                        if (j > endy)endy = j;
+                        if (i < startx) startx = i;
+                        if (j < starty) starty = j;
+                        if (i > endx) endx = i;
+                        if (j > endy) endy = j;
                     }
                 }
             }
@@ -430,10 +819,10 @@ void Person::DoBloodBig(float howmuch, int which)
             for (i = 0; i < 512; i++) {
                 for (j = 0; j < 512; j++) {
                     if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
-                        if (i < startx)startx = i;
-                        if (j < starty)starty = j;
-                        if (i > endx)endx = i;
-                        if (j > endy)endy = j;
+                        if (i < startx) startx = i;
+                        if (j < starty) starty = j;
+                        if (i > endx) endx = i;
+                        if (j > endy) endy = j;
                     }
                 }
             }
@@ -443,12 +832,12 @@ void Person::DoBloodBig(float howmuch, int which)
         starty += offsety;
         endy += offsety;
 
-        if (startx < 0)startx = 0;
-        if (starty < 0)starty = 0;
-        if (endx > 512 - 1)endx = 512 - 1;
-        if (endy > 512 - 1)endy = 512 - 1;
-        if (endx < startx)endx = startx;
-        if (endy < starty)endy = starty;
+        if (startx < 0) startx = 0;
+        if (starty < 0) starty = 0;
+        if (endx > 512 - 1) endx = 512 - 1;
+        if (endy > 512 - 1) endy = 512 - 1;
+        if (endx < startx) endx = startx;
+        if (endy < starty) endy = starty;
 
         startx /= realtexdetail;
         starty /= realtexdetail;
@@ -463,7 +852,8 @@ void Person::DoBloodBig(float howmuch, int which)
                     if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
                         color = Random() % 85 + 170;
                         where = i * skeleton.skinsize * 3 + j * 3;
-                        if (skeleton.skinText[where + 0] > color / 2)skeleton.skinText[where + 0] = color / 2;
+                        if (skeleton.skinText[where + 0] > color / 2)
+                            skeleton.skinText[where + 0] = color / 2;
                         skeleton.skinText[where + 1] = 0;
                         skeleton.skinText[where + 2] = 0;
                     }
@@ -475,7 +865,8 @@ void Person::DoBloodBig(float howmuch, int which)
                     if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
                         color = Random() % 85 + 170;
                         where = i * skeleton.skinsize * 3 + j * 3;
-                        if (skeleton.skinText[where + 0] > color / 2)skeleton.skinText[where + 0] = color / 2;
+                        if (skeleton.skinText[where + 0] > color / 2)
+                            skeleton.skinText[where + 0] = color / 2;
                         skeleton.skinText[where + 1] = 0;
                         skeleton.skinText[where + 2] = 0;
                     }
@@ -500,10 +891,14 @@ void Person::DoBloodBig(float howmuch, int which)
         bleedx = bleedyint + offsety;
         bleedy /= realtexdetail;
         bleedx /= realtexdetail;
-        if (bleedx < 0)bleedx = 0;
-        if (bleedy < 0)bleedy = 0;
-        if (bleedx > skeleton.skinsize - 1)bleedx = skeleton.skinsize - 1;
-        if (bleedy > skeleton.skinsize - 1)bleedy = skeleton.skinsize - 1;
+        if (bleedx < 0)
+            bleedx = 0;
+        if (bleedy < 0)
+            bleedy = 0;
+        if (bleedx > skeleton.skinsize - 1)
+            bleedx = skeleton.skinsize - 1;
+        if (bleedy > skeleton.skinsize - 1)
+            bleedy = skeleton.skinsize - 1;
         direction = abs(Random() % 2) * 2 - 1;
 
     }
@@ -515,12 +910,17 @@ void Person::DoBloodBig(float howmuch, int which)
         if (abs(Random() % 2) == 0) {
             aitype = gethelptype;
             lastseentime = 12;
-        } else aitype = attacktypecutoff;
+        } else
+            aitype = attacktypecutoff;
         ally = 0;
     }
-    if (bleeding > 2)bleeding = 2;
+    if (bleeding > 2)
+        bleeding = 2;
 }
 
+/* EFFECT
+ * similar to DoBloodBig
+ */
 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
 {
     static int i, j;
@@ -529,7 +929,6 @@ bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
     static float rotationpoint;
     static int whichtri;
     static XYZ p1, p2, p3, p0;
-    static XYZ N, temp;
     XYZ bary;
     XYZ gxx, gyy;
     float coordsx, coordsy;
@@ -537,7 +936,8 @@ bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
 
     if (bloodtoggle && decals && tutoriallevel != 1) {
         where -= coords;
-        if (!skeleton.free)where = DoRotation(where, 0, -yaw, 0);
+        if (!skeleton.free)
+            where = DoRotation(where, 0, -yaw, 0);
         //where=scale;
         startpoint = where;
         startpoint.y += 100;
@@ -545,19 +945,14 @@ bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
         endpoint.y -= 100;
         movepoint = 0;
         rotationpoint = 0;
+        // ray testing for a tri in the character model
         whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
         if (whichtri != -1) {
+            // low level geometry math
             p0 = colpoint;
             p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
             p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
             p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
-            /*
-            CrossProduct(p2-p1,p3-p1,&N);
-            CrossProduct(p0-p1,p3-p1,&temp);
-            s =  dotproduct(&temp,&N)/findLength(&N);
-            CrossProduct(p2-p1,p1-p0,&temp);
-            t = dotproduct(&temp,&N)/findLength(&N);
-            r = 1 - (s + t);*/
 
             bary.x = distsq(&p0, &p1);
             bary.y = distsq(&p0, &p2);
@@ -587,42 +982,30 @@ bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
             coordsx = skeleton.drawmodel.Triangles[whichtri].gx[0] * bary.x + skeleton.drawmodel.Triangles[whichtri].gx[1] * bary.y + skeleton.drawmodel.Triangles[whichtri].gx[2] * bary.z;
             coordsy = skeleton.drawmodel.Triangles[whichtri].gy[0] * bary.x + skeleton.drawmodel.Triangles[whichtri].gy[1] * bary.y + skeleton.drawmodel.Triangles[whichtri].gy[2] * bary.z;
 
-            //coordsx=skeleton.drawmodel.Triangles[whichtri].gx[1];
-            //coordsy=skeleton.drawmodel.Triangles[whichtri].gy[1];
-
             if (bleeding <= 0 && spurt) {
                 spurt = 0;
                 for (int i = 0; i < 3; i++) {
+                    // emit blood particles
+                    // FIXME: more copypaste code
                     bloodvel = 0;
-                    if (!skeleton.free) {
-                        bloodvel.z = 10;
-                        bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
-                    }
                     if (skeleton.free) {
                         bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
-                    }
-                    if (skeleton.free)bloodvel += DoRotation(skeleton.joints[skeleton.jointlabels[head]].velocity, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
-                    if (!skeleton.free)bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
-                    if (skeleton.free) {
-                        Sprite::MakeSprite(bloodsprite, skeleton.joints[skeleton.jointlabels[head]].position * scale + coords, bloodvel, 1, 1, 1, .05, 1);
-                        Sprite::MakeSprite(bloodflamesprite, skeleton.joints[skeleton.jointlabels[head]].position * scale + coords, bloodvel, 1, 1, 1, .3, 1);
-                    }
-                    if (!skeleton.free) {
-                        Sprite::MakeSprite(bloodsprite, DoRotation((skeleton.joints[skeleton.jointlabels[head]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
-                        Sprite::MakeSprite(bloodflamesprite, DoRotation((skeleton.joints[skeleton.jointlabels[head]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
+                        bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
+                        Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
+                        Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
+                    } else {
+                        bloodvel.z = 10;
+                        bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
+                        bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
+                        Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
+                        Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
                     }
                 }
             }
+
+            // texture manipulation follows
+
             int offsetx = 0, offsety = 0;
-            /*if(which==225){
-            offsety=Random()%40;
-            offsetx=abs(Random()%120);
-            }
-            if(which==220||which==215){
-            offsety=Random()%20;
-            offsetx=abs(Random()%80);
-            }*/
-            //which=220;
             offsetx = (1 + coordsy) * 512 - 291;
             offsety = coordsx * 512 - 437;
 
@@ -635,10 +1018,10 @@ bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
                 for (i = 0; i < 512; i++) {
                     for (j = 0; j < 512; j++) {
                         if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
-                            if (i < startx)startx = i;
-                            if (j < starty)starty = j;
-                            if (i > endx)endx = i;
-                            if (j > endy)endy = j;
+                            if (i < startx) startx = i;
+                            if (j < starty) starty = j;
+                            if (i > endx) endx = i;
+                            if (j > endy) endy = j;
                         }
                     }
                 }
@@ -646,10 +1029,10 @@ bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
                 for (i = 0; i < 512; i++) {
                     for (j = 0; j < 512; j++) {
                         if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
-                            if (i < startx)startx = i;
-                            if (j < starty)starty = j;
-                            if (i > endx)endx = i;
-                            if (j > endy)endy = j;
+                            if (i < startx) startx = i;
+                            if (j < starty) starty = j;
+                            if (i > endx) endx = i;
+                            if (j > endy) endy = j;
                         }
                     }
                 }
@@ -658,12 +1041,12 @@ bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
             starty += offsety;
             endy += offsety;
 
-            if (startx < 0)startx = 0;
-            if (starty < 0)starty = 0;
-            if (endx > 512 - 1)endx = 512 - 1;
-            if (endy > 512 - 1)endy = 512 - 1;
-            if (endx < startx)endx = startx;
-            if (endy < starty)endy = starty;
+            if (startx < 0) startx = 0;
+            if (starty < 0) starty = 0;
+            if (endx > 512 - 1) endx = 512 - 1;
+            if (endy > 512 - 1) endy = 512 - 1;
+            if (endx < startx) endx = startx;
+            if (endy < starty) endy = starty;
 
             startx /= realtexdetail;
             starty /= realtexdetail;
@@ -678,13 +1061,15 @@ bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
                         if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
                             color = Random() % 85 + 170;
                             where = i * skeleton.skinsize * 3 + j * 3;
-                            if (skeleton.skinText[where + 0] > color / 2)skeleton.skinText[where + 0] = color / 2;
+                            if (skeleton.skinText[where + 0] > color / 2)
+                                skeleton.skinText[where + 0] = color / 2;
                             skeleton.skinText[where + 1] = 0;
                             skeleton.skinText[where + 2] = 0;
                         } else if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= 160 + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= 160 - 4) {
                             color = Random() % 85 + 170;
                             where = i * skeleton.skinsize * 3 + j * 3;
-                            if (skeleton.skinText[where + 0] > color / 2)skeleton.skinText[where + 0] = color / 2;
+                            if (skeleton.skinText[where + 0] > color / 2)
+                                skeleton.skinText[where + 0] = color / 2;
                             skeleton.skinText[where + 1] = 0;
                             skeleton.skinText[where + 2] = 0;
                         }
@@ -696,13 +1081,15 @@ bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
                         if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
                             color = Random() % 85 + 170;
                             where = i * skeleton.skinsize * 3 + j * 3;
-                            if (skeleton.skinText[where + 0] > color / 2)skeleton.skinText[where + 0] = color / 2;
+                            if (skeleton.skinText[where + 0] > color / 2)
+                                skeleton.skinText[where + 0] = color / 2;
                             skeleton.skinText[where + 1] = 0;
                             skeleton.skinText[where + 2] = 0;
                         } else if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= 160 + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= 160 - 4) {
                             color = Random() % 85 + 170;
                             where = i * skeleton.skinsize * 3 + j * 3;
-                            if (skeleton.skinText[where + 0] > color / 2)skeleton.skinText[where + 0] = color / 2;
+                            if (skeleton.skinText[where + 0] > color / 2)
+                                skeleton.skinText[where + 0] = color / 2;
                             skeleton.skinText[where + 1] = 0;
                             skeleton.skinText[where + 2] = 0;
                         }
@@ -715,13 +1102,18 @@ bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
             bleedx = coordsx * 512;
             bleedy /= realtexdetail;
             bleedx /= realtexdetail;
-            if (bleedx < 0)bleedx = 0;
-            if (bleedy < 0)bleedy = 0;
-            if (bleedx > skeleton.skinsize - 1)bleedx = skeleton.skinsize - 1;
-            if (bleedy > skeleton.skinsize - 1)bleedy = skeleton.skinsize - 1;
+            if (bleedx < 0)
+                bleedx = 0;
+            if (bleedy < 0)
+                bleedy = 0;
+            if (bleedx > skeleton.skinsize - 1)
+                bleedx = skeleton.skinsize - 1;
+            if (bleedy > skeleton.skinsize - 1)
+                bleedy = skeleton.skinsize - 1;
             direction = abs(Random() % 2) * 2 - 1;
         }
-        if (whichtri == -1)return 0;
+        if (whichtri == -1)
+            return 0;
     }
     bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
     deathbleeding += bleeding;
@@ -731,15 +1123,20 @@ bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
         if (abs(Random() % 2) == 0) {
             aitype = gethelptype;
             lastseentime = 12;
-        } else aitype = attacktypecutoff;
+        } else
+            aitype = attacktypecutoff;
         ally = 0;
     }
-    if (bleeding > 2)bleeding = 2;
+    if (bleeding > 2)
+        bleeding = 2;
     return 1;
 }
 
 
 
+/* EFFECT
+ * guessing this performs a reversal
+ */
 void Person::Reverse()
 {
     if (!((victim->aitype == playercontrolled
@@ -783,23 +1180,20 @@ void Person::Reverse()
     if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
         if (victim->weaponactive != -1) {
             victim->throwtogglekeydown = 1;
-            weapons[victim->weaponids[0]].owner = -1;
-            weapons[victim->weaponids[0]].velocity = victim->velocity * .2;
-            if (weapons[victim->weaponids[0]].velocity.x == 0)weapons[victim->weaponids[0]].velocity.x = .1;
-            weapons[victim->weaponids[0]].tipvelocity = weapons[victim->weaponids[0]].velocity;
-            weapons[victim->weaponids[0]].missed = 1;
-            weapons[victim->weaponids[0]].freetime = 0;
-            weapons[victim->weaponids[0]].firstfree = 1;
-            weapons[victim->weaponids[0]].physics = 1;
+            XYZ tempVelocity = victim->velocity * .2;
+            if (tempVelocity.x == 0)
+                tempVelocity.x = .1;
+            weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
             victim->num_weapons--;
             if (victim->num_weapons) {
                 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
-                if (victim->weaponstuck == victim->num_weapons)victim->weaponstuck = 0;
+                if (victim->weaponstuck == victim->num_weapons)
+                    victim->weaponstuck = 0;
             }
 
             victim->weaponactive = -1;
-            for (int j = 0; j < numplayers; j++) {
-                player[j].wentforweapon = 0;
+            for (unsigned j = 0; j < Person::players.size(); j++) {
+                Person::players[j]->wentforweapon = 0;
             }
         }
 
@@ -811,23 +1205,20 @@ void Person::Reverse()
     if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
         if (victim->weaponactive != -1) {
             victim->throwtogglekeydown = 1;
-            weapons[victim->weaponids[0]].owner = -1;
-            weapons[victim->weaponids[0]].velocity = victim->velocity * .2;
-            if (weapons[victim->weaponids[0]].velocity.x == 0)weapons[victim->weaponids[0]].velocity.x = .1;
-            weapons[victim->weaponids[0]].tipvelocity = weapons[victim->weaponids[0]].velocity;
-            weapons[victim->weaponids[0]].missed = 1;
-            weapons[victim->weaponids[0]].freetime = 0;
-            weapons[victim->weaponids[0]].firstfree = 1;
-            weapons[victim->weaponids[0]].physics = 1;
+            XYZ tempVelocity = victim->velocity * .2;
+            if (tempVelocity.x == 0)
+                tempVelocity.x = .1;
+            weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
             victim->num_weapons--;
             if (victim->num_weapons) {
                 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
-                if (victim->weaponstuck == victim->num_weapons)victim->weaponstuck = 0;
+                if (victim->weaponstuck == victim->num_weapons)
+                    victim->weaponstuck = 0;
             }
 
             victim->weaponactive = -1;
-            for (int j = 0; j < numplayers; j++) {
-                player[j].wentforweapon = 0;
+            for (unsigned j = 0; j < Person::players.size(); j++) {
+                Person::players[j]->wentforweapon = 0;
             }
         }
         animTarget = staffspinhitreversedanim;
@@ -838,23 +1229,20 @@ void Person::Reverse()
     if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
         if (victim->weaponactive != -1) {
             victim->throwtogglekeydown = 1;
-            weapons[victim->weaponids[0]].owner = -1;
-            weapons[victim->weaponids[0]].velocity = victim->velocity * .2;
-            if (weapons[victim->weaponids[0]].velocity.x == 0)weapons[victim->weaponids[0]].velocity.x = .1;
-            weapons[victim->weaponids[0]].tipvelocity = weapons[victim->weaponids[0]].velocity;
-            weapons[victim->weaponids[0]].missed = 1;
-            weapons[victim->weaponids[0]].freetime = 0;
-            weapons[victim->weaponids[0]].firstfree = 1;
-            weapons[victim->weaponids[0]].physics = 1;
+            XYZ tempVelocity = victim->velocity * .2;
+            if (tempVelocity.x == 0)
+                tempVelocity.x = .1;
+            weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
             victim->num_weapons--;
             if (victim->num_weapons) {
                 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
-                if (victim->weaponstuck == victim->num_weapons)victim->weaponstuck = 0;
+                if (victim->weaponstuck == victim->num_weapons)
+                    victim->weaponstuck = 0;
             }
 
             victim->weaponactive = -1;
-            for (int j = 0; j < numplayers; j++) {
-                player[j].wentforweapon = 0;
+            for (unsigned j = 0; j < Person::players.size(); j++) {
+                Person::players[j]->wentforweapon = 0;
             }
         }
         animTarget = swordslashreversedanim;
@@ -865,23 +1253,20 @@ void Person::Reverse()
     if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
         if (victim->weaponactive != -1) {
             victim->throwtogglekeydown = 1;
-            weapons[victim->weaponids[0]].owner = -1;
-            weapons[victim->weaponids[0]].velocity = victim->velocity * .2;
-            if (weapons[victim->weaponids[0]].velocity.x == 0)weapons[victim->weaponids[0]].velocity.x = .1;
-            weapons[victim->weaponids[0]].tipvelocity = weapons[victim->weaponids[0]].velocity;
-            weapons[victim->weaponids[0]].missed = 1;
-            weapons[victim->weaponids[0]].freetime = 0;
-            weapons[victim->weaponids[0]].firstfree = 1;
-            weapons[victim->weaponids[0]].physics = 1;
+            XYZ tempVelocity = victim->velocity * .2;
+            if (tempVelocity.x == 0)
+                tempVelocity.x = .1;
+            weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
             victim->num_weapons--;
             if (victim->num_weapons) {
                 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
-                if (victim->weaponstuck == victim->num_weapons)victim->weaponstuck = 0;
+                if (victim->weaponstuck == victim->num_weapons)
+                    victim->weaponstuck = 0;
             }
 
             victim->weaponactive = -1;
-            for (int j = 0; j < numplayers; j++) {
-                player[j].wentforweapon = 0;
+            for (unsigned j = 0; j < Person::players.size(); j++) {
+                Person::players[j]->wentforweapon = 0;
             }
         }
         animTarget = knifeslashreversedanim;
@@ -889,7 +1274,7 @@ void Person::Reverse()
         victim->animCurrent = knifeslashreversalanim;
         victim->animTarget = knifeslashreversalanim;
     }
-    if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim && animTarget != swordslashanim) {
+    if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
         victim->targettilt2 = targettilt2;
         victim->frameCurrent = frameCurrent;
         victim->frameTarget = frameTarget;
@@ -899,14 +1284,14 @@ void Person::Reverse()
         victim->coords = coords;
         victim->targetyaw = targetyaw;
         victim->yaw = targetyaw;
-        victim->victim = this;
+        victim->victim = this->shared_from_this();
     }
     if (animTarget == winduppunchanim) {
         animTarget = winduppunchblockedanim;
         victim->animTarget = blockhighleftanim;
         victim->frameTarget = 1;
         victim->target = .5;
-        victim->victim = this;
+        victim->victim = this->shared_from_this();
         victim->targetyaw = targetyaw + 180;
     }
     if (animTarget == wolfslapanim) {
@@ -914,7 +1299,7 @@ void Person::Reverse()
         victim->animTarget = blockhighleftanim;
         victim->frameTarget = 1;
         victim->target = .5;
-        victim->victim = this;
+        victim->victim = this->shared_from_this();
         victim->targetyaw = targetyaw + 180;
     }
     if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
@@ -924,7 +1309,7 @@ void Person::Reverse()
         victim->animTarget = swordslashparryanim;
         victim->frameTarget = 1;
         victim->target = .5;
-        victim->victim = this;
+        victim->victim = this->shared_from_this();
         victim->targetyaw = targetyaw + 180;
 
         if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
@@ -946,32 +1331,28 @@ void Person::Reverse()
             victim->animTarget = staggerbackhighanim;
             victim->targetyaw = targetyaw + 180;
             victim->target = 0;
-            weapons[victim->weaponids[0]].owner = -1;
             aim = DoRotation(facing, 0, 90, 0) * 21;
             aim.y += 7;
-            weapons[victim->weaponids[0]].velocity = aim * -.2;
-            weapons[victim->weaponids[0]].tipvelocity = aim;
-            weapons[victim->weaponids[0]].missed = 1;
-            weapons[victim->weaponids[0]].hitsomething = 0;
-            weapons[victim->weaponids[0]].freetime = 0;
-            weapons[victim->weaponids[0]].firstfree = 1;
-            weapons[victim->weaponids[0]].physics = 1;
+            weapons[victim->weaponids[0]].drop(aim * -.2, aim);
             victim->num_weapons--;
             if (victim->num_weapons) {
                 victim->weaponids[0] = victim->weaponids[num_weapons];
-                if (victim->weaponstuck == victim->num_weapons)victim->weaponstuck = 0;
+                if (victim->weaponstuck == victim->num_weapons)
+                    victim->weaponstuck = 0;
             }
             victim->weaponactive = -1;
-            for (int i = 0; i < numplayers; i++) {
-                player[i].wentforweapon = 0;
+            for (unsigned i = 0; i < Person::players.size(); i++) {
+                Person::players[i]->wentforweapon = 0;
             }
         }
 
         if (abs(Random() % 20) == 0) {
             if (weaponactive != -1) {
                 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
-                    if (weapons[victim->weaponids[0]].getType() == staff)weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
-                    if (weapons[weaponids[0]].getType() == staff)weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
+                    if (weapons[victim->weaponids[0]].getType() == staff)
+                        weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
+                    if (weapons[weaponids[0]].getType() == staff)
+                        weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
 
                     emit_sound_at(swordstaffsound, coords);
                 } else {
@@ -986,24 +1367,18 @@ void Person::Reverse()
             animTarget = staggerbackhighanim;
             targetyaw = targetyaw + 180;
             target = 0;
-            weapons[weaponids[0]].owner = -1;
             aim = DoRotation(facing, 0, 90, 0) * 21;
             aim.y += 7;
-            weapons[weaponids[0]].velocity = aim * -.2;
-            weapons[weaponids[0]].tipvelocity = aim;
-            weapons[weaponids[0]].hitsomething = 0;
-            weapons[weaponids[0]].missed = 1;
-            weapons[weaponids[0]].freetime = 0;
-            weapons[weaponids[0]].firstfree = 1;
-            weapons[weaponids[0]].physics = 1;
+            weapons[victim->weaponids[0]].drop(aim * -.2, aim);
             num_weapons--;
             if (num_weapons) {
                 weaponids[0] = weaponids[num_weapons];
-                if (weaponstuck == num_weapons)weaponstuck = 0;
+                if (weaponstuck == num_weapons)
+                    weaponstuck = 0;
             }
             weaponactive = -1;
-            for (int i = 0; i < numplayers; i++) {
-                player[i].wentforweapon = 0;
+            for (unsigned i = 0; i < Person::players.size(); i++) {
+                Person::players[i]->wentforweapon = 0;
             }
 
 
@@ -1021,7 +1396,8 @@ void Person::Reverse()
                 Normalise(&rotatetarget);
                 victim->targetyaw = -asin(0 - rotatetarget.x);
                 victim->targetyaw *= 360 / 6.28;
-                if (rotatetarget.z < 0)victim->targetyaw = 180 - victim->targetyaw;
+                if (rotatetarget.z < 0)
+                    victim->targetyaw = 180 - victim->targetyaw;
 
                 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
 
@@ -1038,7 +1414,8 @@ void Person::Reverse()
                 Normalise(&rotatetarget);
                 victim->targetyaw = -asin(0 - rotatetarget.x);
                 victim->targetyaw *= 360 / 6.28;
-                if (rotatetarget.z < 0)victim->targetyaw = 180 - victim->targetyaw;
+                if (rotatetarget.z < 0)
+                    victim->targetyaw = 180 - victim->targetyaw;
 
                 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
 
@@ -1051,36 +1428,63 @@ void Person::Reverse()
     velocity = 0;
     victim->velocity = 0;
 
-    if (aitype != playercontrolled)feint = 0;
-    if (aitype != playercontrolled && Random() % 3 == 0 && escapednum < 2 && difficulty == 2)feint = 1;
-    if (aitype != playercontrolled && Random() % 5 == 0 && escapednum < 2 && difficulty == 1)feint = 1;
-    if (aitype != playercontrolled && Random() % 10 == 0 && escapednum < 2 && difficulty == 0)feint = 1;
-
-    if (victim->id == 0 && animation[victim->animTarget].attack == reversal)numreversals++;
+    if (aitype != playercontrolled)
+        feint = 0;
+    if (aitype != playercontrolled && Random() % 3 == 0 && escapednum < 2 && difficulty == 2)
+        feint = 1;
+    if (aitype != playercontrolled && Random() % 5 == 0 && escapednum < 2 && difficulty == 1)
+        feint = 1;
+    if (aitype != playercontrolled && Random() % 10 == 0 && escapednum < 2 && difficulty == 0)
+        feint = 1;
+
+    if (victim->id == 0 && animation[victim->animTarget].attack == reversal)
+        numreversals++;
 }
 
+/* EFFECT
+ * get hurt
+ */
 void Person::DoDamage(float howmuch)
 {
-    if (tutoriallevel != 1)damage += howmuch / power;
-    if (id != 0)damagedealt += howmuch / power;
-    if (id == 0)damagetaken += howmuch / power;
-
-    if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))bonus = 0;
-    if (tutoriallevel != 1)permanentdamage += howmuch / 2 / power;
-    if (tutoriallevel != 1)superpermanentdamage += howmuch / 4 / power;
-    if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)DoBlood(1, 255);
-    if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)DoBlood(1, 255);
+    // subtract health (temporary?)
+    if (tutoriallevel != 1)
+        damage += howmuch / power;
+    // stats?
+    if (id != 0)
+        damagedealt += howmuch / power;
+    if (id == 0)
+        damagetaken += howmuch / power;
+
+    // reset bonuses
+    if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
+        bonus = 0;
+    // subtract health
+    if (tutoriallevel != 1)
+        permanentdamage += howmuch / 2 / power;
+    if (tutoriallevel != 1)
+        superpermanentdamage += howmuch / 4 / power;
+    // visual effects
+    if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
+        DoBlood(1, 255);
+    if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
+        DoBlood(1, 255);
     spurt = 0;
-    if (id == 0)camerashake += howmuch / 100;
-    if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))blackout = damage / damagetolerance;
-    if (blackout > 1)blackout = 1;
-
-    if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))aitype = attacktypecutoff;
+    if (id == 0)
+        camerashake += howmuch / 100;
+    if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))
+        blackout = damage / damagetolerance;
+    if (blackout > 1)
+        blackout = 1;
+
+    // cancel attack?
+    if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))
+        aitype = attacktypecutoff;
     if (tutoriallevel != 1 && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
         if (abs(Random() % 2) == 0) {
             aitype = gethelptype;
             lastseentime = 12;
-        } else aitype = attacktypecutoff;
+        } else
+            aitype = attacktypecutoff;
         ally = 0;
     }
 
@@ -1088,10 +1492,13 @@ void Person::DoDamage(float howmuch)
         XYZ flatvelocity2;
         XYZ flatfacing2;
         for (int i = 0; i < skeleton.num_joints; i++) {
-            if (!skeleton.free)flatvelocity2 = velocity;
-            if (skeleton.free)flatvelocity2 = skeleton.joints[i].velocity;
-            if (!skeleton.free)flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
-            if (skeleton.free)flatfacing2 = skeleton.joints[i].position * scale + coords;
+            if (skeleton.free) {
+                flatvelocity2 = skeleton.joints[i].velocity;
+                flatfacing2 = skeleton.joints[i].position * scale + coords;
+            } else {
+                flatvelocity2 = velocity;
+                flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
+            }
             flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
             flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
             flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
@@ -1105,10 +1512,6 @@ void Person::DoDamage(float howmuch)
         skeleton.free = 2;
         DoDamage(10000);
         RagDoll(0);
-        /*if(autoslomo){
-        slomo=1;
-        slomodelay=.2;
-        }*/
         if (!dead && creature == wolftype) {
             award_bonus(0, Wolfbonus);
         }
@@ -1116,40 +1519,37 @@ void Person::DoDamage(float howmuch)
         coords = 20;
     }
 
+    // play sounds
     if (tutoriallevel != 1 || id == 0)
         if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
             int whichsound = -1;
 
             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 (i == 0)
+                    whichsound = snarlsound;
+                if (i == 1)
+                    whichsound = snarl2sound;
             }
             if (creature == rabbittype) {
                 int i = abs(Random() % 2);
-                if (i == 0)whichsound = rabbitpainsound;
-                if (i == 1 && damage > damagetolerance)whichsound = rabbitpain1sound;
-                envsound[numenvsounds] = coords;
-                envsoundvol[numenvsounds] = 16;
-                envsoundlife[numenvsounds] = .4;
-                numenvsounds++;
-                //if(i==2)whichsound=rabbitpain2sound;
+                if (i == 0)
+                    whichsound = rabbitpainsound;
+                if (i == 1 && damage > damagetolerance)
+                    whichsound = rabbitpain1sound;
             }
 
             if (whichsound != -1) {
                 emit_sound_at(whichsound, coords);
+                addEnvSound(coords);
             }
         }
     speechdelay = .3;
-
-    //if(permanentdamage>=damagetolerance&&howmuch<50)permanentdamage=damagetolerance-1;
-    //if(damage>=damagetolerance&&howmuch<30&&!dead)damage=damagetolerance-1;
 }
 
+/* EFFECT
+ * calculate/animate head facing direction?
+ */
 void Person::DoHead()
 {
     static XYZ rotatearound;
@@ -1165,40 +1565,55 @@ void Person::DoHead()
         while (targetheadyaw > 180)targetheadyaw -= 360;
         while (targetheadyaw < -180)targetheadyaw += 360;
 
-        if (targetheadyaw > 160)targetheadpitch = targetheadpitch * -1;
-        if (targetheadyaw < -160)targetheadpitch = targetheadpitch * -1;
-        if (targetheadyaw > 160)targetheadyaw = targetheadyaw - 180;
-        if (targetheadyaw < -160)targetheadyaw = targetheadyaw + 180;
-
-        if (targetheadpitch > 120)targetheadpitch = 120;
-        if (targetheadpitch < -120)targetheadpitch = -120;
-        if (targetheadyaw > 120)targetheadyaw = 120;
-        if (targetheadyaw < -120)targetheadyaw = -120;
-
-        if (!isIdle())targetheadpitch = 0;
+        if (targetheadyaw > 160)
+            targetheadpitch = targetheadpitch * -1;
+        if (targetheadyaw < -160)
+            targetheadpitch = targetheadpitch * -1;
+        if (targetheadyaw > 160)
+            targetheadyaw = targetheadyaw - 180;
+        if (targetheadyaw < -160)
+            targetheadyaw = targetheadyaw + 180;
+
+        if (targetheadpitch > 120)
+            targetheadpitch = 120;
+        if (targetheadpitch < -120)
+            targetheadpitch = -120;
+        if (targetheadyaw > 120)
+            targetheadyaw = 120;
+        if (targetheadyaw < -120)
+            targetheadyaw = -120;
+
+        if (!isIdle())
+            targetheadpitch = 0;
         if (isIdle()) {
-            if (targetheadyaw > 80)targetheadyaw = 80;
-            if (targetheadyaw < -80)targetheadyaw = -80;
-            if (targetheadpitch > 50)targetheadpitch = 50;
-            if (targetheadpitch < -50)targetheadpitch = -50;
-        }
-
-        if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)headyaw = targetheadyaw;
+            if (targetheadyaw > 80)
+                targetheadyaw = 80;
+            if (targetheadyaw < -80)
+                targetheadyaw = -80;
+            if (targetheadpitch > 50)
+                targetheadpitch = 50;
+            if (targetheadpitch < -50)
+                targetheadpitch = -50;
+        }
+
+        if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
+            headyaw = targetheadyaw;
         else if (headyaw > targetheadyaw) {
             headyaw -= multiplier * lookspeed;
         } else if (headyaw < targetheadyaw) {
             headyaw += multiplier * lookspeed;
         }
 
-        if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)headpitch = targetheadpitch;
+        if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
+            headpitch = targetheadpitch;
         else if (headpitch > targetheadpitch) {
             headpitch -= multiplier * lookspeed / 2;
         } else if (headpitch < targetheadpitch) {
             headpitch += multiplier * lookspeed / 2;
         }
 
-        rotatearound = skeleton.joints[skeleton.jointlabels[neck]].position;
-        skeleton.joints[skeleton.jointlabels[head]].position = rotatearound + DoRotation(skeleton.joints[skeleton.jointlabels[head]].position - rotatearound, headpitch, 0, 0);
+        rotatearound = jointPos(neck);
+        jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
 
         facing = 0;
         facing.z = -1;
@@ -1219,8 +1634,7 @@ void Person::DoHead()
 
         skeleton.specialforward[0] = facing;
         //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
-        static int i;
-        for (i = 0; i < skeleton.num_muscles; i++) {
+        for (int i = 0; i < skeleton.num_muscles; i++) {
             if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
                 skeleton.FindRotationMuscle(i, animTarget);
             }
@@ -1228,14 +1642,19 @@ void Person::DoHead()
     }
 }
 
+/* EFFECT
+ * ragdolls character?
+ */
 void Person::RagDoll(bool checkcollision)
 {
     static XYZ change;
     static int l, i, j;
     static float speed;
     if (!skeleton.free) {
-        if (id == 0)numfalls++;
-        if (id == 0 && isFlip())numflipfail++;
+        if (id == 0)
+            numfalls++;
+        if (id == 0 && isFlip())
+            numflipfail++;
 
         escapednum = 0;
 
@@ -1253,27 +1672,26 @@ void Person::RagDoll(bool checkcollision)
         freefall = 1;
         skeleton.freefall = 1;
 
-        if (!isnormal(velocity.x))velocity.x = 0;
-        if (!isnormal(velocity.y))velocity.y = 0;
-        if (!isnormal(velocity.z))velocity.z = 0;
-        if (!isnormal(yaw))yaw = 0;
-        if (!isnormal(coords.x))coords = 0;
-        if (!isnormal(tilt))tilt = 0;
-        if (!isnormal(tilt2))tilt2 = 0;
+        if (!isnormal(velocity.x)) velocity.x = 0;
+        if (!isnormal(velocity.y)) velocity.y = 0;
+        if (!isnormal(velocity.z)) velocity.z = 0;
+        if (!isnormal(yaw)) yaw = 0;
+        if (!isnormal(coords.x)) coords = 0;
+        if (!isnormal(tilt)) tilt = 0;
+        if (!isnormal(tilt2)) tilt2 = 0;
 
-        for (i = 0; i < skeleton.num_joints; i++) {
+        for (int i = 0; i < skeleton.num_joints; 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);
-            if (!isnormal(skeleton.joints[i].position.x))skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
-            if (!isnormal(skeleton.joints[i].position.x))skeleton.joints[i].position = skeleton.joints[i].position;
-            if (!isnormal(skeleton.joints[i].position.x))skeleton.joints[i].position = coords;
+            if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
+            if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
             skeleton.joints[i].position.y += .1;
             skeleton.joints[i].oldposition = skeleton.joints[i].position;
             skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
         }
 
-        for (i = 0; i < skeleton.num_joints; i++) {
+        for (int i = 0; i < skeleton.num_joints; i++) {
             skeleton.joints[i].velocity = 0;
             skeleton.joints[i].velchange = 0;
         }
@@ -1289,13 +1707,16 @@ void Person::RagDoll(bool checkcollision)
         if (animation[animCurrent].speed[frameCurrent] > animation[animTarget].speed[frameTarget]) {
             speed = animation[animCurrent].speed[frameCurrent] * 2;
         }
-        if (transspeed)speed = transspeed * 2;
+        if (transspeed)
+            speed = transspeed * 2;
 
         speed *= speedmult;
 
-        for (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);
-            else skeleton.joints[i].velocity = velocity / scale + facing * 5;
+        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);
+            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;
@@ -1344,30 +1765,25 @@ void Person::RagDoll(bool checkcollision)
         updatedelay = 0;
 
         velocity = 0;
-        for (i = 0; i < skeleton.num_joints; i++) {
+        for (int i = 0; i < skeleton.num_joints; i++) {
             velocity += skeleton.joints[i].velocity * scale;
         }
         velocity /= skeleton.num_joints;
 
+        // drop weapon
         if (Random() % 2 == 0) {
             if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
-                weapons[weaponids[0]].owner = -1;
-                weapons[weaponids[0]].hitsomething = 0;
-                weapons[weaponids[0]].velocity = skeleton.joints[skeleton.jointlabels[righthand]].velocity * scale * -.3;
+                weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
                 weapons[weaponids[0]].velocity.x += .01;
-                weapons[weaponids[0]].tipvelocity = skeleton.joints[skeleton.jointlabels[righthand]].velocity * scale;
-                weapons[weaponids[0]].missed = 1;
-                weapons[weaponids[0]].freetime = 0;
-                weapons[weaponids[0]].firstfree = 1;
-                weapons[weaponids[0]].physics = 1;
                 num_weapons--;
                 if (num_weapons) {
                     weaponids[0] = weaponids[num_weapons];
-                    if (weaponstuck == num_weapons)weaponstuck = 0;
+                    if (weaponstuck == num_weapons)
+                        weaponstuck = 0;
                 }
                 weaponactive = -1;
-                for (i = 0; i < numplayers; i++) {
-                    player[i].wentforweapon = 0;
+                for (unsigned i = 0; i < Person::players.size(); i++) {
+                    Person::players[i]->wentforweapon = 0;
                 }
             }
         }
@@ -1381,67 +1797,71 @@ void Person::RagDoll(bool checkcollision)
 
 
 
-void Person::FootLand(int which, float opacity)
+/* EFFECT
+ */
+void Person::FootLand(bodyparts 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(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
-            if (which == 1)footpoint = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 0, yaw, 0) * scale + coords;
-            //footpoint.y=coords.y;
-            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) {
-            footvel = velocity / 5;
-            if (footvel.y < .8)footvel.y = .8;
-            if (which == 0)footpoint = DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
-            if (which == 1)footpoint = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 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)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(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
-            if (which == 1)footpoint = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 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) {
+            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 (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
             footvel = velocity / 5;
-            if (footvel.y < .8)footvel.y = .8;
-            if (which == 0)footpoint = DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
-            if (which == 1)footpoint = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 0, yaw, 0) * scale + coords;
+            if (footvel.y < .8)
+                footvel.y = .8;
+            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 * 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)terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
-        } else if (isLanding() || animTarget == jumpupanim || isLandhard()) {
+            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) {
+                    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()) {
             footvel = velocity / 5;
-            if (footvel.y < .8)footvel.y = .8;
-            if (which == 0)footpoint = DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
-            if (which == 1)footpoint = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 0, yaw, 0) * scale + coords;
-            //footpoint.y=coords.y;
-            if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
+            if (footvel.y < .8)
+                footvel.y = .8;
+            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
+ * make a puff effect at a body part (dust effect?)
+ */
 void Person::Puff(int whichlabel)
 {
     static XYZ footvel, footpoint;
 
     footvel = 0;
-    footpoint = DoRotation(skeleton.joints[skeleton.jointlabels[whichlabel]].position, 0, yaw, 0) * scale + coords;
+    footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
     Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
 }
 
-Joint& Person::getJointFor(int bodypart)
-{
-    return skeleton.joints[skeleton.jointlabels[bodypart]];
-}
-
+/* EFFECT
+ * I think I added this in an attempt to clean up code
+ */
 void Person::setAnimation(int animation)
 {
     animTarget = animation;
@@ -1449,13 +1869,17 @@ void Person::setAnimation(int animation)
     target = 0;
 }
 
-void   Person::DoAnimations()
+/* EFFECT
+ * MONSTER
+ * TODO: ???
+ */
+void Person::DoAnimations()
 {
     if (!skeleton.free) {
-        int i = 0;
         static float oldtarget;
 
-        if (isIdle() && animCurrent != getIdle())normalsupdatedelay = 0;
+        if (isIdle() && animCurrent != getIdle())
+            normalsupdatedelay = 0;
 
         if (animTarget == tempanim || animCurrent == tempanim) {
             animation[tempanim] = tempanimation;
@@ -1474,8 +1898,10 @@ void     Person::DoAnimations()
                 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
                 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
             }
-            if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))landhard = 1;
-            if (!crouchkeydown && velocity.y >= -15)landhard = 0;
+            if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
+                landhard = 1;
+            if (!crouchkeydown && velocity.y >= -15)
+                landhard = 0;
         }
         if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
             XYZ targfacing;
@@ -1484,27 +1910,35 @@ void    Person::DoAnimations()
 
             targfacing = DoRotation(targfacing, 0, targetyaw, 0);
 
-            if (normaldotproduct(targfacing, velocity) >= -.3)animTarget = flipanim;
-            else animTarget = backflipanim;
+            if (normaldotproduct(targfacing, velocity) >= -.3)
+                animTarget = flipanim;
+            else
+                animTarget = backflipanim;
             crouchtogglekeydown = 1;
             frameTarget = 0;
             target = 0;
 
-            if (id == 0)numflipped++;
+            if (id == 0)
+                numflipped++;
         }
 
-        if (animation[animTarget].attack != reversed)feint = 0;
+        if (animation[animTarget].attack != reversed)
+            feint = 0;
         if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
             crouchtogglekeydown = 0;
-            if (aitype == playercontrolled)feint = 0;
+            if (aitype == playercontrolled)
+                feint = 0;
         } else {
-            if (!crouchtogglekeydown && animation[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))feint = 1;
-            if (!isFlip())crouchtogglekeydown = 1;
+            if (!crouchtogglekeydown && animation[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
+                feint = 1;
+            if (!isFlip())
+                crouchtogglekeydown = 1;
         }
 
 
         if (animation[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
-            if (detail)normalsupdatedelay = 0;
+            if (detail)
+                normalsupdatedelay = 0;
         }
 
         if (target >= 1) {
@@ -1516,16 +1950,19 @@ void    Person::DoAnimations()
             }
 
             if (animTarget == rabbittacklinganim && frameTarget == 1) {
-                //if(victim->aitype==attacktypecutoff&&Random()%2==0&&victim->stunned<=0&&animation[victim->animTarget].attack==neutral&&victim->id!=0)Reverse();
-                if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)Reverse();
+                if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
+                    Reverse();
                 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
-                    if (normaldotproduct(victim->facing, facing) > 0)victim->animTarget = rabbittackledbackanim;
-                    else victim->animTarget = rabbittackledfrontanim;
+                    if (normaldotproduct(victim->facing, facing) > 0)
+                        victim->animTarget = rabbittackledbackanim;
+                    else
+                        victim->animTarget = rabbittackledfrontanim;
                     victim->frameTarget = 2;
                     victim->target = 0;
                     victim->yaw = yaw;
                     victim->targetyaw = yaw;
-                    if (victim->aitype == gethelptype)victim->DoDamage(victim->damagetolerance - victim->damage);
+                    if (victim->aitype == gethelptype)
+                        victim->DoDamage(victim->damagetolerance - victim->damage);
                     //victim->DoDamage(30);
                     if (creature == wolftype) {
                         DoBloodBig(0, 255);
@@ -1540,8 +1977,10 @@ 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 (weapons[weaponids[0]].getType() == knife) {
-                    if (weaponactive == -1)weaponactive = 0;
-                    else if (weaponactive == 0)weaponactive = -1;
+                    if (weaponactive == -1)
+                        weaponactive = 0;
+                    else if (weaponactive == 0)
+                        weaponactive = -1;
 
                     if (weaponactive == -1) {
                         emit_sound_at(knifesheathesound, coords);
@@ -1558,45 +1997,59 @@ void    Person::DoAnimations()
                     int whichsound;
                     if (onterrain) {
                         if (terrain.getOpacity(coords.x, coords.z) < .2) {
-                            if (animation[animTarget].label[frameTarget] == 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] == 1)
+                                whichsound = footstepsound;
+                            else
+                                whichsound = footstepsound2;
+                            if (animation[animTarget].label[frameTarget] == 1)
+                                FootLand(leftfoot, 1);
+                            if (animation[animTarget].label[frameTarget] == 2)
+                                FootLand(rightfoot, 1);
                             if (animation[animTarget].label[frameTarget] == 3 && isRun()) {
-                                FootLand(1, 1);
-                                FootLand(0, 1);
+                                FootLand(rightfoot, 1);
+                                FootLand(leftfoot, 1);
                             }
 
                         }
                         if (terrain.getOpacity(coords.x, coords.z) >= .2) {
-                            if (animation[animTarget].label[frameTarget] == 1)whichsound = footstepsound3;
-                            else whichsound = footstepsound4;
+                            if (animation[animTarget].label[frameTarget] == 1)
+                                whichsound = footstepsound3;
+                            else
+                                whichsound = footstepsound4;
                         }
                     }
                     if (!onterrain) {
-                        if (animation[animTarget].label[frameTarget] == 1)whichsound = footstepsound3;
-                        else whichsound = footstepsound4;
+                        if (animation[animTarget].label[frameTarget] == 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) {
-                            i = abs(Random() % 3);
-                            if (i == 0)whichsound = lowwhooshsound;
-                            if (i == 1)whichsound = midwhooshsound;
-                            if (i == 2)whichsound = highwhooshsound;
+                            unsigned r = abs(Random() % 3);
+                            if (r == 0)
+                                whichsound = lowwhooshsound;
+                            if (r == 1)
+                                whichsound = midwhooshsound;
+                            if (r == 2)
+                                whichsound = highwhooshsound;
                         }
-                        if (animation[animTarget].attack == neutral)whichsound = movewhooshsound;
-                    } else if (animation[animTarget].label[frameTarget] == 4)whichsound = knifeswishsound;
-                    if (animation[animTarget].label[frameTarget] == 8 && tutoriallevel != 1)whichsound = landsound2;
+                        if (animation[animTarget].attack == neutral)
+                            whichsound = movewhooshsound;
+                    } else if (animation[animTarget].label[frameTarget] == 4)
+                        whichsound = knifeswishsound;
+                    if (animation[animTarget].label[frameTarget] == 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) {
@@ -1613,25 +2066,22 @@ void    Person::DoAnimations()
                             int whichsound = -1;
                             if (animation[animTarget].label[frameTarget] == 4 && aitype != playercontrolled) {
                                 if (animation[animTarget].attack != neutral) {
-                                    i = abs(Random() % 4);
+                                    unsigned r = abs(Random() % 4);
                                     if (creature == rabbittype) {
-                                        if (i == 0)whichsound = rabbitattacksound;
-                                        if (i == 1)whichsound = rabbitattack2sound;
-                                        if (i == 2)whichsound = rabbitattack3sound;
-                                        if (i == 3)whichsound = rabbitattack4sound;
+                                        if (r == 0) whichsound = rabbitattacksound;
+                                        if (r == 1) whichsound = rabbitattack2sound;
+                                        if (r == 2) whichsound = rabbitattack3sound;
+                                        if (r == 3) whichsound = rabbitattack4sound;
                                     }
                                     if (creature == wolftype) {
-                                        if (i == 0)whichsound = barksound;
-                                        if (i == 1)whichsound = bark2sound;
-                                        if (i == 2)whichsound = bark3sound;
-                                        if (i == 3)whichsound = barkgrowlsound;
+                                        if (r == 0) whichsound = barksound;
+                                        if (r == 1) whichsound = bark2sound;
+                                        if (r == 2) whichsound = bark3sound;
+                                        if (r == 3) whichsound = barkgrowlsound;
                                     }
                                     speechdelay = .3;
                                 }
-                                //if(animation[animTarget].attack==neutral)whichsound=movewhooshsound;
                             }
-                            //else if(animation[animTarget].label[frameTarget]==4)whichsound=knifeswishsound;
-                            //if(animation[animTarget].label[frameTarget]==8)whichsound=landsound2;
 
                             if (whichsound != -1) {
                                 emit_sound_at(whichsound, coords);
@@ -1641,8 +2091,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;
@@ -1652,7 +2102,7 @@ void      Person::DoAnimations()
             frameTarget++;
 
             if (animTarget == removeknifeanim && animation[animTarget].label[frameCurrent] == 5) {
-                for (i = 0; i < weapons.size(); i++) {
+                for (unsigned i = 0; i < weapons.size(); i++) {
                     if (weapons[i].owner == -1)
                         if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
                             if (distsq(&coords, &weapons[i].position) >= 1) {
@@ -1660,32 +2110,27 @@ void    Person::DoAnimations()
                                     emit_sound_at(knifedrawsound, coords, 128.);
                                 }
 
-                                weaponactive = 0;
-                                weapons[i].owner = id;
-                                if (num_weapons > 0) {
-                                    weaponids[num_weapons] = weaponids[0];
-                                }
-                                num_weapons++;
-                                weaponids[0] = i;
+                                takeWeapon(i);
                             }
                         }
                 }
             }
 
             if (animTarget == crouchremoveknifeanim && animation[animTarget].label[frameCurrent] == 5) {
-                for (i = 0; i < weapons.size(); i++) {
+                for (unsigned i = 0; i < weapons.size(); i++) {
                     bool willwork = true;
                     if (weapons[i].owner != -1)
-                        if (player[weapons[i].owner].weaponstuck != -1)
-                            if (player[weapons[i].owner].weaponids[player[weapons[i].owner].weaponstuck] == i)
-                                if (player[weapons[i].owner].num_weapons > 1)willwork = 0;
-                    if ((weapons[i].owner == -1) || (hasvictim && weapons[i].owner == victim->id && victim->skeleton.free))
+                        if (Person::players[weapons[i].owner]->weaponstuck != -1)
+                            if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
+                                if (Person::players[weapons[i].owner]->num_weapons > 1)
+                                    willwork = 0;
+                    if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
                         if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
                             if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
                                 bool fleshstuck = false;
                                 if (weapons[i].owner != -1)
                                     if (victim->weaponstuck != -1) {
-                                        if (victim->weaponids[victim->weaponstuck] == i) {
+                                        if (victim->weaponids[victim->weaponstuck] == int(i)) {
                                             fleshstuck = true;
                                         }
                                     }
@@ -1696,12 +2141,12 @@ void    Person::DoAnimations()
                                         emit_sound_at(knifedrawsound, coords, 128.);
                                     }
                                 }
-                                weaponactive = 0;
                                 if (weapons[i].owner != -1) {
-
-                                    victim = &player[weapons[i].owner];
-                                    if (victim->num_weapons == 1)victim->num_weapons = 0;
-                                    else victim->num_weapons = 1;
+                                    victim = Person::players[weapons[i].owner];
+                                    if (victim->num_weapons == 1)
+                                        victim->num_weapons = 0;
+                                    else
+                                        victim->num_weapons = 1;
 
                                     //victim->weaponactive=-1;
                                     victim->skeleton.longdead = 0;
@@ -1721,37 +2166,35 @@ void    Person::DoAnimations()
                                     footvel = 0;
                                     footpoint = weapons[i].position;
                                     if (victim->weaponstuck != -1) {
-                                        if (victim->weaponids[victim->weaponstuck] == i) {
-                                            if (bloodtoggle)Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
+                                        if (victim->weaponids[victim->weaponstuck] == int(i)) {
+                                            if (bloodtoggle)
+                                                Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
                                             weapons[i].bloody = 2;
                                             weapons[i].blooddrip = 5;
                                             victim->weaponstuck = -1;
                                         }
                                     }
                                     if (victim->num_weapons > 0) {
-                                        if (victim->weaponstuck != 0 && victim->weaponstuck != -1)victim->weaponstuck = 0;
-                                        if (victim->weaponids[0] == i)
+                                        if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
+                                            victim->weaponstuck = 0;
+                                        if (victim->weaponids[0] == int(i))
                                             victim->weaponids[0] = victim->weaponids[victim->num_weapons];
                                     }
 
-                                    victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * 6;
-                                    victim->skeleton.joints[victim->skeleton.jointlabels[neck]].velocity += relative * 6;
-                                    victim->skeleton.joints[victim->skeleton.jointlabels[rightshoulder]].velocity += relative * 6;
-                                    victim->skeleton.joints[victim->skeleton.jointlabels[leftshoulder]].velocity += relative * 6;
-                                }
-                                weapons[i].owner = id;
-                                if (num_weapons > 0) {
-                                    weaponids[num_weapons] = weaponids[0];
+                                    victim->jointVel(abdomen) += relative * 6;
+                                    victim->jointVel(neck) += relative * 6;
+                                    victim->jointVel(rightshoulder) += relative * 6;
+                                    victim->jointVel(leftshoulder) += relative * 6;
                                 }
-                                num_weapons++;
-                                weaponids[0] = i;
+                                takeWeapon(i);
                             }
                         }
                 }
             }
 
             if (animCurrent == drawleftanim && animation[animTarget].label[frameCurrent] == 5) {
-                if (weaponactive == -1)weaponactive = 0;
+                if (weaponactive == -1)
+                    weaponactive = 0;
                 else if (weaponactive == 0) {
                     weaponactive = -1;
                     if (num_weapons == 2) {
@@ -1775,18 +2218,24 @@ void    Person::DoAnimations()
                 Normalise(&rotatetarget);
                 targetyaw = -asin(0 - rotatetarget.x);
                 targetyaw *= 360 / 6.28;
-                if (rotatetarget.z < 0)targetyaw = 180 - targetyaw;
+                if (rotatetarget.z < 0)
+                    targetyaw = 180 - targetyaw;
 
-                if (animTarget == walljumprightkickanim)targetyaw += 40;
-                if (animTarget == walljumpleftkickanim)targetyaw -= 40;
+                if (animTarget == walljumprightkickanim)
+                    targetyaw += 40;
+                if (animTarget == walljumpleftkickanim)
+                    targetyaw -= 40;
             }
 
             bool dojumpattack;
             dojumpattack = 0;
-            if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))dojumpattack = 1;
+            if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
+                dojumpattack = 1;
             if (hasvictim)
-                if (distsq(&victim->coords, &/*player[i].*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)dojumpattack = 1;
-            if (!hostile)dojumpattack = 0;
+                if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
+                    dojumpattack = 1;
+            if (!hostile)
+                dojumpattack = 0;
             if (dojumpattack) {
                 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
                     animTarget = rabbittackleanim;
@@ -1802,17 +2251,17 @@ void    Person::DoAnimations()
                 targetloc = velocity;
                 Normalise(&targetloc);
                 targetloc += coords;
-                for (i = 0; i < numplayers; i++) {
+                for (unsigned i = 0; i < Person::players.size(); i++) {
                     if (i != id)
-                        if (distsq(&targetloc, &player[i].coords) < closestdist || closestdist == 0) {
-                            closestdist = distsq(&targetloc, &player[i].coords);
+                        if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
+                            closestdist = distsq(&targetloc, &Person::players[i]->coords);
                             closestid = i;
                         }
                 }
                 if (closestid != -1)
-                    if (closestdist < 5 && !player[closestid].dead && animation[player[closestid].animTarget].height != lowheight && player[closestid].animTarget != backhandspringanim) {
+                    if (closestdist < 5 && !Person::players[closestid]->dead && animation[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
                         hasvictim = 1;
-                        victim = &player[closestid];
+                        victim = Person::players[closestid];
                         coords = victim->coords;
                         animCurrent = rabbittacklinganim;
                         animTarget = rabbittacklinganim;
@@ -1824,7 +2273,8 @@ void      Person::DoAnimations()
                             Normalise(&rotatetarget);
                             targetyaw = -asin(0 - rotatetarget.x);
                             targetyaw *= 360 / 6.28;
-                            if (rotatetarget.z < 0)targetyaw = 180 - targetyaw;
+                            if (rotatetarget.z < 0)
+                                targetyaw = 180 - targetyaw;
                         }
                         if (animTarget != rabbitrunninganim) {
                             emit_sound_at(jumpsound, coords, 128.);
@@ -1834,20 +2284,22 @@ void    Person::DoAnimations()
 
             //Move impacts
             float damagemult = 1 * power;
-            if (creature == wolftype)damagemult = 2.5 * power;
+            if (creature == wolftype)
+                damagemult = 2.5 * power;
             if (hasvictim) {
                 damagemult /= victim->damagetolerance / 200;
             }
-            //if(onfire)damagemult=3;
             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) {
                         escapednum = 0;
-                        if (id == 0)camerashake += .4;
+                        if (id == 0)
+                            camerashake += .4;
                         if (Random() % 2 || creature == wolftype) {
                             victim->spurt = 1;
                             DoBlood(.2, 250);
-                            if (creature == wolftype)DoBloodBig(0, 250);
+                            if (creature == wolftype)
+                                DoBloodBig(0, 250);
                         }
                         if (tutoriallevel != 1) {
                             emit_sound_at(heavyimpactsound, victim->coords, 128.);
@@ -1863,11 +2315,10 @@ void    Person::DoAnimations()
                         relative.y = 0;
                         Normalise(&relative);
                         relative = DoRotation(relative, 0, -90, 0);
-                        for (i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
                         }
-                        victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 200;
-                        //FootLand(1,2);
+                        victim->jointVel(head) += relative * damagemult * 200;
                         victim->Puff(head);
                         victim->DoDamage(damagemult * 100 / victim->protectionhead);
 
@@ -1878,10 +2329,12 @@ 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) {
                         escapednum = 0;
-                        if (id == 0)camerashake += .4;
+                        if (id == 0)
+                            camerashake += .4;
                         if (Random() % 2 || creature == wolftype) {
                             victim->spurt = 1;
-                            if (creature == wolftype)DoBloodBig(0, 235);
+                            if (creature == wolftype)
+                                DoBloodBig(0, 235);
                         }
                         emit_sound_at(whooshhitsound, victim->coords);
                         if (creature == wolftype) {
@@ -1897,11 +2350,10 @@ void    Person::DoAnimations()
                         relative.y -= 1;
                         Normalise(&relative);
                         relative = DoRotation(relative, 0, 90, 0);
-                        for (i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
                             victim->skeleton.joints[i].velocity += relative * damagemult * 20;
                         }
-                        victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 100;
-                        //FootLand(1,2);
+                        victim->jointVel(head) += relative * damagemult * 100;
                         victim->Puff(head);
                         victim->DoDamage(damagemult * 50 / victim->protectionhead);
                     }
@@ -1910,7 +2362,8 @@ void      Person::DoAnimations()
                 if (animTarget == walljumprightkickanim && animation[animTarget].label[frameCurrent] == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
                         escapednum = 0;
-                        if (id == 0)camerashake += .4;
+                        if (id == 0)
+                            camerashake += .4;
                         victim->spurt = 1;
                         DoBlood(.2, 250);
                         if (tutoriallevel != 1) {
@@ -1927,11 +2380,10 @@ void    Person::DoAnimations()
                         relative.y = 0;
                         Normalise(&relative);
                         relative = DoRotation(relative, 0, -90, 0);
-                        for (i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
                         }
-                        victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 200;
-                        //FootLand(1,2);
+                        victim->jointVel(head) += relative * damagemult * 200;
                         victim->Puff(head);
                         victim->DoDamage(damagemult * 150 / victim->protectionhead);
 
@@ -1945,7 +2397,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) {
                         escapednum = 0;
-                        if (id == 0)camerashake += .4;
+                        if (id == 0)
+                            camerashake += .4;
                         victim->spurt = 1;
                         DoBlood(.2, 250);
                         if (tutoriallevel != 1) {
@@ -1962,11 +2415,10 @@ void    Person::DoAnimations()
                         relative.y = 0;
                         Normalise(&relative);
                         relative = DoRotation(relative, 0, 90, 0);
-                        for (i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
                         }
-                        victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 200;
-                        //FootLand(1,2);
+                        victim->jointVel(head) += relative * damagemult * 200;
                         victim->Puff(head);
                         victim->DoDamage(damagemult * 150 / victim->protectionhead);
 
@@ -1980,7 +2432,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) {
                         escapednum = 0;
-                        if (id == 0)camerashake += .4;
+                        if (id == 0)
+                            camerashake += .4;
                         if (Random() % 2) {
                             victim->spurt = 1;
                             DoBlood(.2, 235);
@@ -1991,11 +2444,10 @@ void    Person::DoAnimations()
                         relative = victim->coords - coords;
                         relative.y = 0;
                         Normalise(&relative);
-                        for (i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
                             victim->skeleton.joints[i].velocity += relative * damagemult * 30;
                         }
-                        victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 100;
-                        //FootLand(1,2);
+                        victim->jointVel(head) += relative * damagemult * 100;
                         victim->Puff(head);
                         victim->DoDamage(damagemult * 50 / victim->protectionhead);
                     }
@@ -2004,7 +2456,8 @@ void      Person::DoAnimations()
                 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 8) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
                         escapednum = 0;
-                        if (id == 0)camerashake += .2;
+                        if (id == 0)
+                            camerashake += .2;
                         emit_sound_at(whooshhitsound, victim->coords, 128.);
 
                         victim->skeleton.longdead = 0;
@@ -2012,7 +2465,7 @@ void      Person::DoAnimations()
                         victim->skeleton.broken = 0;
                         victim->skeleton.spinny = 1;
 
-                        for (i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
                             victim->skeleton.joints[i].velchange = 0;
                             victim->skeleton.joints[i].delay = 0;
                             victim->skeleton.joints[i].locked = 0;
@@ -2023,21 +2476,22 @@ void    Person::DoAnimations()
                         relative = 0;
                         relative.y = 1;
                         Normalise(&relative);
-                        for (i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.num_joints; 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;
                             victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
                         }
                         victim->Puff(abdomen);
-                        victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity.y = relative.y * 400;
+                        victim->jointVel(abdomen).y = relative.y * 400;
                     }
                 }
 
                 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
                         escapednum = 0;
-                        if (id == 0)camerashake += .4;
+                        if (id == 0)
+                            camerashake += .4;
                         if (tutoriallevel != 1) {
                             emit_sound_at(heavyimpactsound, coords, 128.);
                         }
@@ -2045,7 +2499,7 @@ void      Person::DoAnimations()
                         relative = victim->coords - coords;
                         relative.y = 0;
                         Normalise(&relative);
-                        for (i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
                             victim->skeleton.joints[i].velocity += relative * damagemult * 90;
                         }
                         victim->Puff(abdomen);
@@ -2054,14 +2508,15 @@ void    Person::DoAnimations()
                             slomodelay = .2;
                         }
                         victim->DoDamage(damagemult * 500 / victim->protectionhigh);
-                        victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 300;
+                        victim->jointVel(abdomen) += relative * damagemult * 300;
                     }
                 }
 
                 if (animTarget == dropkickanim && animation[animTarget].label[frameCurrent] == 7) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
                         escapednum = 0;
-                        if (id == 0)camerashake += .4;
+                        if (id == 0)
+                            camerashake += .4;
                         if (tutoriallevel != 1) {
                             emit_sound_at(thudsound, coords);
                         }
@@ -2071,7 +2526,7 @@ void      Person::DoAnimations()
                         victim->skeleton.broken = 0;
                         victim->skeleton.spinny = 1;
 
-                        for (i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
                             victim->skeleton.joints[i].velchange = 0;
                             //victim->skeleton.joints[i].delay=0;
                             victim->skeleton.joints[i].locked = 0;
@@ -2081,7 +2536,7 @@ void      Person::DoAnimations()
                         Normalise(&relative);
                         relative.y += .3;
                         Normalise(&relative);
-                        for (i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
                             victim->skeleton.joints[i].velocity += relative * damagemult * 20;
                         }
                         if (!victim->dead)
@@ -2089,19 +2544,20 @@ void    Person::DoAnimations()
 
                         victim->Puff(abdomen);
                         victim->DoDamage(damagemult * 20 / victim->protectionhigh);
-                        victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 200;
+                        victim->jointVel(abdomen) += relative * damagemult * 200;
                         staggerdelay = .5;
-                        if (!victim->dead)staggerdelay = 1.2;
+                        if (!victim->dead)
+                            staggerdelay = 1.2;
 
 
                     }
                 }
 
                 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 5) {
-                    //if(id==0)camerashake+=.4;
 
                     if (hasvictim)
-                        if (!victim->skeleton.free)hasvictim = 0;
+                        if (!victim->skeleton.free)
+                            hasvictim = 0;
 
                     if (!hasvictim) {
                         terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
@@ -2117,7 +2573,8 @@ void      Person::DoAnimations()
                             if (weapons[weaponids[weaponactive]].getType() == knife) {
                                 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
                                 where -= victim->coords;
-                                if (!victim->skeleton.free)where = DoRotation(where, 0, -victim->yaw, 0);
+                                if (!victim->skeleton.free)
+                                    where = DoRotation(where, 0, -victim->yaw, 0);
                                 //where=scale;
                                 startpoint = where;
                                 startpoint.y += 100;
@@ -2127,21 +2584,25 @@ void    Person::DoAnimations()
                             if (weapons[weaponids[weaponactive]].getType() == sword) {
                                 where = weapons[weaponids[weaponactive]].position;
                                 where -= victim->coords;
-                                if (!victim->skeleton.free)where = DoRotation(where, 0, -victim->yaw, 0);
+                                if (!victim->skeleton.free)
+                                    where = DoRotation(where, 0, -victim->yaw, 0);
                                 startpoint = where;
                                 where = weapons[weaponids[weaponactive]].tippoint;
                                 where -= victim->coords;
-                                if (!victim->skeleton.free)where = DoRotation(where, 0, -victim->yaw, 0);
+                                if (!victim->skeleton.free)
+                                    where = DoRotation(where, 0, -victim->yaw, 0);
                                 endpoint = where;
                             }
                             if (weapons[weaponids[weaponactive]].getType() == staff) {
                                 where = weapons[weaponids[weaponactive]].position;
                                 where -= victim->coords;
-                                if (!victim->skeleton.free)where = DoRotation(where, 0, -victim->yaw, 0);
+                                if (!victim->skeleton.free)
+                                    where = DoRotation(where, 0, -victim->yaw, 0);
                                 startpoint = where;
                                 where = weapons[weaponids[weaponactive]].tippoint;
                                 where -= victim->coords;
-                                if (!victim->skeleton.free)where = DoRotation(where, 0, -victim->yaw, 0);
+                                if (!victim->skeleton.free)
+                                    where = DoRotation(where, 0, -victim->yaw, 0);
                                 endpoint = where;
                             }
                             movepoint = 0;
@@ -2154,13 +2615,14 @@ void    Person::DoAnimations()
                                     if (!victim->dead)
                                         award_bonus(id, FinishedBonus);
                                 }
-                                if (bloodtoggle)weapons[weaponids[weaponactive]].bloody = 2;
+                                if (bloodtoggle)
+                                    weapons[weaponids[weaponactive]].bloody = 2;
 
                                 victim->skeleton.longdead = 0;
                                 victim->skeleton.free = 1;
                                 victim->skeleton.broken = 0;
 
-                                for (i = 0; i < victim->skeleton.num_joints; i++) {
+                                for (int i = 0; i < victim->skeleton.num_joints; i++) {
                                     victim->skeleton.joints[i].velchange = 0;
                                     victim->skeleton.joints[i].locked = 0;
                                     //victim->skeleton.joints[i].velocity=0;
@@ -2200,11 +2662,13 @@ void    Person::DoAnimations()
 
                             where = weapons[weaponids[weaponactive]].position;
                             where -= victim->coords;
-                            if (!victim->skeleton.free)where = DoRotation(where, 0, -victim->yaw, 0);
+                            if (!victim->skeleton.free)
+                                where = DoRotation(where, 0, -victim->yaw, 0);
                             startpoint = where;
                             where = weapons[weaponids[weaponactive]].tippoint;
                             where -= victim->coords;
-                            if (!victim->skeleton.free)where = DoRotation(where, 0, -victim->yaw, 0);
+                            if (!victim->skeleton.free)
+                                where = DoRotation(where, 0, -victim->yaw, 0);
                             endpoint = where;
 
                             movepoint = 0;
@@ -2223,11 +2687,13 @@ void    Person::DoAnimations()
 
                             where = weapons[weaponids[weaponactive]].position;
                             where -= victim->coords;
-                            if (!victim->skeleton.free)where = DoRotation(where, 0, -victim->yaw, 0);
+                            if (!victim->skeleton.free)
+                                where = DoRotation(where, 0, -victim->yaw, 0);
                             startpoint = where;
                             where = weapons[weaponids[weaponactive]].tippoint;
                             where -= victim->coords;
-                            if (!victim->skeleton.free)where = DoRotation(where, 0, -victim->yaw, 0);
+                            if (!victim->skeleton.free)
+                                where = DoRotation(where, 0, -victim->yaw, 0);
                             endpoint = where;
 
                             movepoint = 0;
@@ -2246,7 +2712,7 @@ void      Person::DoAnimations()
                                 victim->skeleton.free = 1;
                                 victim->skeleton.broken = 0;
 
-                                for (i = 0; i < victim->skeleton.num_joints; i++) {
+                                for (int i = 0; i < victim->skeleton.num_joints; i++) {
                                     victim->skeleton.joints[i].velchange = 0;
                                     victim->skeleton.joints[i].locked = 0;
                                     //victim->skeleton.joints[i].velocity=0;
@@ -2257,14 +2723,15 @@ void    Person::DoAnimations()
                                 relative.y = 10;
                                 Normalise(&relative);
                                 //victim->Puff(abdomen);
-                                if (bloodtoggle)Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
+                                if (bloodtoggle)
+                                    Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
 
                                 if (victim->bloodloss < victim->damagetolerance) {
                                     victim->bloodloss += 1000;
                                     victim->bled = 0;
                                 }
 
-                                victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 20;
+                                victim->jointVel(abdomen) += relative * damagemult * 20;
                             }
                         }
                     }
@@ -2277,7 +2744,8 @@ void      Person::DoAnimations()
                 if (animTarget == upunchanim && animation[animTarget].label[frameCurrent] == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
                         escapednum = 0;
-                        if (id == 0)camerashake += .4;
+                        if (id == 0)
+                            camerashake += .4;
                         if (Random() % 2) {
                             victim->spurt = 1;
                             DoBlood(.2, 235);
@@ -2291,10 +2759,10 @@ void    Person::DoAnimations()
                         relative = victim->coords - coords;
                         relative.y = 0;
                         Normalise(&relative);
-                        for (i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
                             victim->skeleton.joints[i].velocity = relative * 30;
                         }
-                        victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 150;
+                        victim->jointVel(head) += relative * damagemult * 150;
 
                         victim->frameTarget = 0;
                         victim->animTarget = staggerbackhardanim;
@@ -2314,7 +2782,8 @@ void      Person::DoAnimations()
                 if (animTarget == winduppunchanim && animation[animTarget].label[frameCurrent] == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
                         escapednum = 0;
-                        if (id == 0)camerashake += .4;
+                        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 (tutoriallevel != 1) {
                                 emit_sound_at(thudsound, victim->coords);
@@ -2337,10 +2806,10 @@ void    Person::DoAnimations()
                         Normalise(&relative);
                         relative.y = .3;
                         Normalise(&relative);
-                        for (i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
                             victim->skeleton.joints[i].velocity = relative * 5;
                         }
-                        victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 400;
+                        victim->jointVel(abdomen) += relative * damagemult * 400;
 
                         victim->frameTarget = 0;
                         victim->animTarget = staggerbackhardanim;
@@ -2357,7 +2826,8 @@ void      Person::DoAnimations()
 
                 if (animTarget == blockhighleftanim && animation[animTarget].label[frameCurrent] == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
-                        if (victim->id == 0)camerashake += .4;
+                        if (victim->id == 0)
+                            camerashake += .4;
                         emit_sound_at(landsound2, victim->coords);
 
                         Puff(righthand);
@@ -2366,12 +2836,15 @@ void    Person::DoAnimations()
 
                 if (animTarget == swordslashparryanim && animation[animTarget].label[frameCurrent] == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
-                        if (victim->id == 0)camerashake += .4;
+                        if (victim->id == 0)
+                            camerashake += .4;
 
                         if (weaponactive != -1) {
                             if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
-                                if (weapons[victim->weaponids[0]].getType() == staff)weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
-                                if (weapons[weaponids[0]].getType() == staff)weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
+                                if (weapons[victim->weaponids[0]].getType() == staff)
+                                    weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
+                                if (weapons[weaponids[0]].getType() == staff)
+                                    weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
 
                                 emit_sound_at(swordstaffsound, victim->coords);
                             } else {
@@ -2387,19 +2860,9 @@ void     Person::DoAnimations()
                     if (weaponactive != -1) {
                         escapednum = 0;
                         XYZ aim;
-                        weapons[weaponids[0]].owner = -1;
-                        aim = victim->coords + DoRotation(victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].position, 0, victim->yaw, 0) * victim->scale + victim->velocity * findDistance(&victim->coords, &coords) / 50 - (coords + DoRotation(skeleton.joints[skeleton.jointlabels[righthand]].position, 0, yaw, 0) * scale);
+                        aim = victim->coords + DoRotation(victim->jointPos(abdomen), 0, victim->yaw, 0) * victim->scale + victim->velocity * findDistance(&victim->coords, &coords) / 50 - (coords + DoRotation(jointPos(righthand), 0, yaw, 0) * scale);
                         Normalise(&aim);
-                        /*if(victim->animTarget==jumpupanim||victim->animTarget==jumpdownanim){
-                        aim=DoRotation(aim,(float)abs(Random()%15)-7,(float)abs(Random()%15)-7,0);
-                        }*/
-                        weapons[weaponids[0]].velocity = aim * 50;
-                        weapons[weaponids[0]].tipvelocity = aim * 50;
-                        weapons[weaponids[0]].missed = 0;
-                        weapons[weaponids[0]].hitsomething = 0;
-                        weapons[weaponids[0]].freetime = 0;
-                        weapons[weaponids[0]].firstfree = 1;
-                        weapons[weaponids[0]].physics = 0;
+                        weapons[weaponids[0]].thrown(aim * 50);
                         num_weapons--;
                         if (num_weapons) {
                             weaponids[0] = weaponids[num_weapons];
@@ -2412,13 +2875,14 @@ void    Person::DoAnimations()
                     if (hasvictim)
                         if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*animation[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
                             escapednum = 0;
-                            if (tutoriallevel != 1)victim->DoBloodBig(1.5 / victim->armorhigh, 225);
+                            if (tutoriallevel != 1)
+                                victim->DoBloodBig(1.5 / victim->armorhigh, 225);
 
                             award_bonus(id, Slicebonus);
                             if (tutoriallevel != 1) {
                                 emit_sound_at(knifeslicesound, victim->coords);
                             }
-                            //victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity+=relative*damagemult*200;
+                            //victim->jointVel(abdomen)+=relative*damagemult*200;
                             if (animation[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
                                 if (victim->id != 0 || difficulty == 2) {
                                     victim->frameTarget = 0;
@@ -2429,21 +2893,25 @@ void    Person::DoAnimations()
                             }
                             victim->lowreversaldelay = 0;
                             victim->highreversaldelay = 0;
-                            if (aitype != playercontrolled)weaponmissdelay = .6;
+                            if (aitype != playercontrolled)
+                                weaponmissdelay = .6;
 
-                            if (tutoriallevel != 1)if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)weapons[weaponids[weaponactive]].bloody = 1;
-                            if (tutoriallevel != 1)weapons[weaponids[weaponactive]].blooddrip += 3;
+                            if (tutoriallevel != 1)
+                                if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
+                                    weapons[weaponids[weaponactive]].bloody = 1;
+                            if (tutoriallevel != 1)
+                                weapons[weaponids[weaponactive]].blooddrip += 3;
 
                             XYZ footvel, footpoint;
                             footvel = 0;
                             if (skeleton.free) {
-                                footpoint = (victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].position + victim->skeleton.joints[victim->skeleton.jointlabels[neck]].position) / 2 * victim->scale + victim->coords;
-                            }
-                            if (!skeleton.free) {
-                                footpoint = DoRotation((victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].position + victim->skeleton.joints[victim->skeleton.jointlabels[neck]].position) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
+                                footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
+                            } else {
+                                footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
                             }
                             if (tutoriallevel != 1) {
-                                if (bloodtoggle)Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
+                                if (bloodtoggle)
+                                    Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
                                 footvel = DoRotation(facing, 0, 90, 0) * .8;
                                 //footvel.y-=.3;
                                 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
@@ -2463,12 +2931,14 @@ void    Person::DoAnimations()
                             award_bonus(id, Slashbonus);
                             escapednum = 0;
                             if (tutoriallevel != 1) {
-                                if (normaldotproduct(victim->facing, victim->coords - coords) < 0)victim->DoBloodBig(2 / victim->armorhigh, 190);
-                                else victim->DoBloodBig(2 / victim->armorhigh, 185);
+                                if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
+                                    victim->DoBloodBig(2 / victim->armorhigh, 190);
+                                else
+                                    victim->DoBloodBig(2 / victim->armorhigh, 185);
                                 victim->deathbleeding = 1;
                                 emit_sound_at(swordslicesound, victim->coords);
                             }
-                            //victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity+=relative*damagemult*200;
+                            //victim->jointVel(abdomen)+=relative*damagemult*200;
                             if (tutoriallevel != 1) {
                                 victim->frameTarget = 0;
                                 victim->animTarget = staggerbackhardanim;
@@ -2477,7 +2947,8 @@ void      Person::DoAnimations()
                             }
 
                             if (tutoriallevel != 1) {
-                                if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)weapons[weaponids[weaponactive]].bloody = 1;
+                                if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
+                                    weapons[weaponids[weaponactive]].bloody = 1;
                                 weapons[weaponids[weaponactive]].blooddrip += 3;
 
                                 float bloodlossamount;
@@ -2489,12 +2960,12 @@ void    Person::DoAnimations()
                                 XYZ footvel, footpoint;
                                 footvel = 0;
                                 if (skeleton.free) {
-                                    footpoint = (victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].position + victim->skeleton.joints[victim->skeleton.jointlabels[neck]].position) / 2 * victim->scale + victim->coords;
-                                }
-                                if (!skeleton.free) {
-                                    footpoint = DoRotation((victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].position + victim->skeleton.joints[victim->skeleton.jointlabels[neck]].position) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
+                                    footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
+                                } else {
+                                    footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
                                 }
-                                if (bloodtoggle)Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
+                                if (bloodtoggle)
+                                    Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
                                 footvel = DoRotation(facing, 0, 90, 0) * .8;
                                 footvel.y -= .3;
                                 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
@@ -2505,8 +2976,10 @@ void     Person::DoAnimations()
                         } else {
                             if (victim->weaponactive != -1) {
                                 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
-                                    if (weapons[victim->weaponids[0]].getType() == staff)weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
-                                    if (weapons[weaponids[0]].getType() == staff)weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
+                                    if (weapons[victim->weaponids[0]].getType() == staff)
+                                        weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
+                                    if (weapons[weaponids[0]].getType() == staff)
+                                        weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
 
                                     emit_sound_at(swordstaffsound, victim->coords);
                                 } else {
@@ -2522,24 +2995,18 @@ void    Person::DoAnimations()
                             victim->animTarget = staggerbackhighanim;
                             victim->targetyaw = targetyaw + 180;
                             victim->target = 0;
-                            weapons[victim->weaponids[0]].owner = -1;
                             aim = DoRotation(facing, 0, 90, 0) * 21;
                             aim.y += 7;
-                            weapons[victim->weaponids[0]].velocity = aim * -.2;
-                            weapons[victim->weaponids[0]].tipvelocity = aim;
-                            weapons[victim->weaponids[0]].missed = 1;
-                            weapons[weaponids[0]].hitsomething = 0;
-                            weapons[victim->weaponids[0]].freetime = 0;
-                            weapons[victim->weaponids[0]].firstfree = 1;
-                            weapons[victim->weaponids[0]].physics = 1;
+                            weapons[victim->weaponids[0]].drop(aim * -.2, aim);
                             victim->num_weapons--;
                             if (victim->num_weapons) {
                                 victim->weaponids[0] = victim->weaponids[num_weapons];
-                                if (victim->weaponstuck == victim->num_weapons)victim->weaponstuck = 0;
+                                if (victim->weaponstuck == victim->num_weapons)
+                                    victim->weaponstuck = 0;
                             }
                             victim->weaponactive = -1;
-                            for (i = 0; i < numplayers; i++) {
-                                player[i].wentforweapon = 0;
+                            for (unsigned i = 0; i < Person::players.size(); i++) {
+                                Person::players[i]->wentforweapon = 0;
                             }
 
                         }
@@ -2551,7 +3018,8 @@ void      Person::DoAnimations()
                         if (tutoriallevel != 1) {
                             weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
                             escapednum = 0;
-                            if (id == 0)camerashake += .4;
+                            if (id == 0)
+                                camerashake += .4;
                             if (Random() % 2 || creature == wolftype) {
                                 victim->spurt = 1;
                             }
@@ -2565,12 +3033,11 @@ void    Person::DoAnimations()
                         relative = DoRotation(relative, 0, 90, 0);
                         relative.y -= 1;
                         Normalise(&relative);
-                        for (i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
                             victim->skeleton.joints[i].velocity += relative * damagemult * 60;
                         }
-                        victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 230;
-                        victim->skeleton.joints[victim->skeleton.jointlabels[neck]].velocity += relative * damagemult * 230;
-                        //FootLand(1,2);
+                        victim->jointVel(head) += relative * damagemult * 230;
+                        victim->jointVel(neck) += relative * damagemult * 230;
                         victim->Puff(head);
                         if (tutoriallevel != 1) {
                             victim->DoDamage(damagemult * 120 / victim->protectionhigh);
@@ -2585,7 +3052,8 @@ void      Person::DoAnimations()
                         if (tutoriallevel != 1) {
                             weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
                             escapednum = 0;
-                            if (id == 0)camerashake += .4;
+                            if (id == 0)
+                                camerashake += .4;
                             if (Random() % 2 || creature == wolftype) {
                                 victim->spurt = 1;
                             }
@@ -2597,12 +3065,11 @@ void    Person::DoAnimations()
                         relative.y = 0;
                         Normalise(&relative);
                         relative = DoRotation(relative, 0, -90, 0);
-                        for (i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
                         }
-                        victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 220;
-                        victim->skeleton.joints[victim->skeleton.jointlabels[neck]].velocity += relative * damagemult * 220;
-                        //FootLand(1,2);
+                        victim->jointVel(head) += relative * damagemult * 220;
+                        victim->jointVel(neck) += relative * damagemult * 220;
                         victim->Puff(head);
                         if (tutoriallevel != 1) {
                             victim->DoDamage(damagemult * 350 / victim->protectionhead);
@@ -2616,8 +3083,10 @@ void     Person::DoAnimations()
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
                         escapednum = 0;
                         if (tutoriallevel != 1) {
-                            if (!victim->dead)weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
-                            if (id == 0)camerashake += .4;
+                            if (!victim->dead)
+                                weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
+                            if (id == 0)
+                                camerashake += .4;
                             if (Random() % 2 || creature == wolftype) {
                                 victim->spurt = 1;
                             }
@@ -2627,7 +3096,7 @@ void      Person::DoAnimations()
                         victim->skeleton.free = 1;
                         victim->skeleton.broken = 0;
 
-                        for (i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
                             victim->skeleton.joints[i].velchange = 0;
                             victim->skeleton.joints[i].locked = 0;
                             //victim->skeleton.joints[i].velocity=0;
@@ -2636,25 +3105,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 (i = 0; i < victim->skeleton.num_joints; i++) {
+                            for (int i = 0; i < victim->skeleton.num_joints; i++) {
                                 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
                             }
-                            //FootLand(1,2);
-                            victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 40;
+                            victim->jointVel(abdomen) += relative * damagemult * 40;
                         }
                         if (victim->dead) {
-                            for (i = 0; i < victim->skeleton.num_joints; i++) {
+                            for (int i = 0; i < victim->skeleton.num_joints; i++) {
                                 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
                             }
-                            //FootLand(1,2);
-                            //victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity+=relative*damagemult*20;
                         }
                         victim->Puff(abdomen);
                         if (tutoriallevel != 1) {
@@ -2670,7 +3132,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) {
                         escapednum = 0;
-                        if (id == 0)camerashake += .4;
+                        if (id == 0)
+                            camerashake += .4;
                         XYZ relative;
                         relative = victim->coords - coords;
                         relative.y = 0;
@@ -2684,27 +3147,29 @@ void    Person::DoAnimations()
                                 DoBlood(.2, 250);
                             }
                             victim->RagDoll(0);
-                            for (i = 0; i < victim->skeleton.num_joints; i++) {
+                            for (int i = 0; i < victim->skeleton.num_joints; i++) {
                                 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
                             }
-                            victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 200;
+                            victim->jointVel(head) += relative * damagemult * 200;
                             if (tutoriallevel != 1) {
                                 emit_sound_at(heavyimpactsound, victim->coords, 128.);
                             }
                             victim->Puff(head);
                             victim->DoDamage(damagemult * 100 / victim->protectionhead);
-                            if (victim->howactive == typesleeping)victim->DoDamage(damagemult * 150 / victim->protectionhead);
+                            if (victim->howactive == typesleeping)
+                                victim->DoDamage(damagemult * 150 / victim->protectionhead);
                             if (creature == wolftype) {
                                 emit_sound_at(clawslicesound, victim->coords, 128.);
                                 victim->spurt = 1;
                                 victim->DoBloodBig(2 / victim->armorhead, 175);
                             }
                         } else {
-                            if (victim->damage >= victim->damagetolerance)victim->RagDoll(0);
-                            for (i = 0; i < victim->skeleton.num_joints; i++) {
+                            if (victim->damage >= victim->damagetolerance)
+                                victim->RagDoll(0);
+                            for (int i = 0; i < victim->skeleton.num_joints; i++) {
                                 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
                             }
-                            victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 200;
+                            victim->jointVel(abdomen) += relative * damagemult * 200;
                             victim->frameTarget = 0;
                             victim->animTarget = staggerbackhighanim;
                             victim->targetyaw = targetyaw + 180;
@@ -2725,9 +3190,12 @@ void     Person::DoAnimations()
                 }
 
                 if (animTarget == sweepanim && animation[animTarget].label[frameCurrent] == 5) {
-                    if (victim->animTarget != jumpupanim && distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim != this) {
+                    if ((victim->animTarget != jumpupanim) &&
+                        (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
+                        (victim != this->shared_from_this())) {
                         escapednum = 0;
-                        if (id == 0)camerashake += .2;
+                        if (id == 0)
+                            camerashake += .2;
                         if (tutoriallevel != 1) {
                             emit_sound_at(landsound2, victim->coords, 128.);
                         }
@@ -2739,12 +3207,12 @@ void    Person::DoAnimations()
                         if (animation[victim->animTarget].height == middleheight || animation[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
                             victim->RagDoll(0);
 
-                            for (i = 0; i < victim->skeleton.num_joints; i++) {
+                            for (int i = 0; i < victim->skeleton.num_joints; i++) {
                                 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
                             }
                             relative = DoRotation(relative, 0, -90, 0);
                             relative.y += .1;
-                            for (i = 0; i < victim->skeleton.num_joints; i++) {
+                            for (int i = 0; i < victim->skeleton.num_joints; 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;
                             }
@@ -2752,16 +3220,17 @@ void    Person::DoAnimations()
                             victim->Puff(leftankle);
                             victim->DoDamage(damagemult * 40 / victim->protectionlow);
                         } else {
-                            if (victim->damage >= victim->damagetolerance)victim->RagDoll(0);
-                            for (i = 0; i < victim->skeleton.num_joints; i++) {
+                            if (victim->damage >= victim->damagetolerance)
+                                victim->RagDoll(0);
+                            for (int i = 0; i < victim->skeleton.num_joints; i++) {
                                 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
                             }
                             relative = DoRotation(relative, 0, -90, 0);
-                            for (i = 0; i < victim->skeleton.num_joints; i++) {
+                            for (int i = 0; i < victim->skeleton.num_joints; 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;
                             }
-                            victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 200;
+                            victim->jointVel(abdomen) += relative * damagemult * 200;
                             victim->frameTarget = 0;
                             victim->animTarget = staggerbackhighanim;
                             victim->targetyaw = targetyaw + 180;
@@ -2781,7 +3250,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) {
                     escapednum = 0;
-                    if (id == 0)camerashake += .4;
+                    if (id == 0)
+                        camerashake += .4;
                     if (Random() % 2) {
                         victim->spurt = 1;
                         DoBlood(.2, 230);
@@ -2799,12 +3269,10 @@ void    Person::DoAnimations()
                     relative = victim->coords - oldcoords;
                     relative.y = 0;
                     Normalise(&relative);
-                    //relative=DoRotation(relative,0,-90,0);
-                    for (i = 0; i < victim->skeleton.num_joints; i++) {
+                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
                         victim->skeleton.joints[i].velocity += relative * damagemult * 40;
                     }
-                    victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 200;
-                    //FootLand(1,2);
+                    victim->jointVel(abdomen) += relative * damagemult * 200;
                     victim->Puff(abdomen);
                     victim->DoDamage(damagemult * 150 / victim->protectionhigh);
 
@@ -2813,18 +3281,11 @@ void    Person::DoAnimations()
 
                 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && animation[animTarget].label[frameCurrent] == 5) {
                     if (victim->weaponactive != -1 && victim->num_weapons > 0) {
-                        if (weapons[victim->weaponids[victim->weaponactive]].owner == victim->id) {
-                            weapons[victim->weaponids[victim->weaponactive]].owner = id;
-                            weaponactive = 0;
-                            if (num_weapons > 0) {
-                                weaponids[num_weapons] = weaponids[victim->weaponactive];
-                            }
-                            num_weapons++;
-                            weaponids[0] = victim->weaponids[victim->weaponactive];
+                        if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
+                            takeWeapon(victim->weaponids[victim->weaponactive]);
                             victim->num_weapons--;
                             if (victim->num_weapons > 0) {
                                 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
-                                //if(victim->weaponstuck==victim->num_weapons)victim->weaponstuck=0;
                             }
                             victim->weaponactive = -1;
                         }
@@ -2833,7 +3294,8 @@ void      Person::DoAnimations()
 
                 if (animTarget == staffhitreversalanim && animation[animTarget].label[frameCurrent] == 5) {
                     escapednum = 0;
-                    if (id == 0)camerashake += .4;
+                    if (id == 0)
+                        camerashake += .4;
                     if (Random() % 2) {
                         victim->spurt = 1;
                         DoBlood(.2, 230);
@@ -2844,19 +3306,18 @@ void    Person::DoAnimations()
                     relative = victim->coords - oldcoords;
                     relative.y = 0;
                     Normalise(&relative);
-                    //relative=DoRotation(relative,0,-90,0);
-                    for (i = 0; i < victim->skeleton.num_joints; i++) {
+                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
                         victim->skeleton.joints[i].velocity += relative * damagemult * 30;
                     }
-                    victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 200;
-                    //FootLand(1,2);
+                    victim->jointVel(abdomen) += relative * damagemult * 200;
                     victim->Puff(head);
                     victim->DoDamage(damagemult * 70 / victim->protectionhigh);
                 }
 
                 if (animTarget == staffspinhitreversalanim && animation[animTarget].label[frameCurrent] == 7) {
                     escapednum = 0;
-                    if (id == 0)camerashake += .4;
+                    if (id == 0)
+                        camerashake += .4;
                     if (Random() % 2) {
                         victim->spurt = 1;
                         DoBlood(.2, 230);
@@ -2874,12 +3335,10 @@ void    Person::DoAnimations()
                     relative = victim->coords - oldcoords;
                     relative.y = 0;
                     Normalise(&relative);
-                    //relative=DoRotation(relative,0,-90,0);
-                    for (i = 0; i < victim->skeleton.num_joints; i++) {
+                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
                         victim->skeleton.joints[i].velocity += relative * damagemult * 30;
                     }
-                    victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 200;
-                    //FootLand(1,2);
+                    victim->jointVel(abdomen) += relative * damagemult * 200;
                     victim->Puff(head);
                     victim->DoDamage(damagemult * 70 / victim->protectionhigh);
                 }
@@ -2891,19 +3350,18 @@ void    Person::DoAnimations()
                     relative = facing;
                     relative.y = 0;
                     Normalise(&relative);
-                    //relative*=-1;
                     relative.y -= .1;
-                    for (i = 0; i < victim->skeleton.num_joints; i++) {
+                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
                         victim->skeleton.joints[i].velocity += relative * damagemult * 70;
                     }
-                    victim->skeleton.joints[victim->skeleton.jointlabels[lefthand]].velocity *= .1;
-                    victim->skeleton.joints[victim->skeleton.jointlabels[leftwrist]].velocity *= .2;
-                    victim->skeleton.joints[victim->skeleton.jointlabels[leftelbow]].velocity *= .5;
-                    victim->skeleton.joints[victim->skeleton.jointlabels[leftshoulder]].velocity *= .7;
-                    victim->skeleton.joints[victim->skeleton.jointlabels[righthand]].velocity *= .1;
-                    victim->skeleton.joints[victim->skeleton.jointlabels[rightwrist]].velocity *= .2;
-                    victim->skeleton.joints[victim->skeleton.jointlabels[rightelbow]].velocity *= .5;
-                    victim->skeleton.joints[victim->skeleton.jointlabels[rightshoulder]].velocity *= .7;
+                    victim->jointVel(lefthand) *= .1;
+                    victim->jointVel(leftwrist) *= .2;
+                    victim->jointVel(leftelbow) *= .5;
+                    victim->jointVel(leftshoulder) *= .7;
+                    victim->jointVel(righthand) *= .1;
+                    victim->jointVel(rightwrist) *= .2;
+                    victim->jointVel(rightelbow) *= .5;
+                    victim->jointVel(rightshoulder) *= .7;
 
                     victim->Puff(abdomen);
                     victim->DoDamage(damagemult * 90 / victim->protectionhigh);
@@ -2912,17 +3370,20 @@ void    Person::DoAnimations()
 
                     bool doslice;
                     doslice = 0;
-                    if (weaponactive != -1 || creature == wolftype)doslice = 1;
-                    if (creature == rabbittype && weaponactive != -1)if (weapons[weaponids[0]].getType() == staff)doslice = 0;
+                    if (weaponactive != -1 || creature == wolftype)
+                        doslice = 1;
+                    if (creature == rabbittype && weaponactive != -1)
+                        if (weapons[weaponids[0]].getType() == staff)
+                            doslice = 0;
                     if (doslice) {
                         if (weaponactive != -1) {
                             victim->DoBloodBig(2 / victim->armorhigh, 225);
                             emit_sound_at(knifeslicesound, victim->coords);
-                            if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)weapons[weaponids[weaponactive]].bloody = 1;
+                            if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
+                                weapons[weaponids[weaponactive]].bloody = 1;
                             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);
@@ -2939,26 +3400,26 @@ void    Person::DoAnimations()
                     relative = facing;
                     relative.y = 0;
                     Normalise(&relative);
-                    //relative*=-1;
                     relative.y -= .1;
-                    for (i = 0; i < victim->skeleton.num_joints; i++) {
+                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
                         victim->skeleton.joints[i].velocity += relative * damagemult * 70;
                     }
-                    victim->skeleton.joints[victim->skeleton.jointlabels[lefthand]].velocity *= .1 - 1;
-                    victim->skeleton.joints[victim->skeleton.jointlabels[leftwrist]].velocity *= .2 - 1;
-                    victim->skeleton.joints[victim->skeleton.jointlabels[leftelbow]].velocity *= .5 - 1;
-                    victim->skeleton.joints[victim->skeleton.jointlabels[leftshoulder]].velocity *= .7 - 1;
-                    victim->skeleton.joints[victim->skeleton.jointlabels[righthand]].velocity *= .1 - 1;
-                    victim->skeleton.joints[victim->skeleton.jointlabels[rightwrist]].velocity *= .2 - 1;
-                    victim->skeleton.joints[victim->skeleton.jointlabels[rightelbow]].velocity *= .5 - 1;
-                    victim->skeleton.joints[victim->skeleton.jointlabels[rightshoulder]].velocity *= .7 - 1;
+                    victim->jointVel(lefthand) *= .1 - 1;
+                    victim->jointVel(leftwrist) *= .2 - 1;
+                    victim->jointVel(leftelbow) *= .5 - 1;
+                    victim->jointVel(leftshoulder) *= .7 - 1;
+                    victim->jointVel(righthand) *= .1 - 1;
+                    victim->jointVel(rightwrist) *= .2 - 1;
+                    victim->jointVel(rightelbow) *= .5 - 1;
+                    victim->jointVel(rightshoulder) *= .7 - 1;
 
                     award_bonus(id, swordreversebonus);
                 }
 
                 if (hasvictim && animTarget == knifeslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
                     escapednum = 0;
-                    if (id == 0)camerashake += .4;
+                    if (id == 0)
+                        camerashake += .4;
                     if (Random() % 2) {
                         victim->spurt = 1;
                         DoBlood(.2, 230);
@@ -2972,11 +3433,10 @@ void    Person::DoAnimations()
                     relative.y = 0;
                     Normalise(&relative);
                     relative = DoRotation(relative, 0, -90, 0);
-                    for (i = 0; i < victim->skeleton.num_joints; i++) {
+                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
                         victim->skeleton.joints[i].velocity += relative * damagemult * 40;
                     }
-                    victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 200;
-                    //FootLand(1,2);
+                    victim->jointVel(abdomen) += relative * damagemult * 200;
                     victim->Puff(abdomen);
                     victim->DoDamage(damagemult * 30 / victim->protectionhigh);
 
@@ -2991,22 +3451,26 @@ void    Person::DoAnimations()
                     relative = facing * -1;
                     relative.y = -3;
                     Normalise(&relative);
-                    if (victim->id == 0)relative /= 30;
-                    for (i = 0; i < victim->skeleton.num_joints; i++) {
+                    if (victim->id == 0)
+                        relative /= 30;
+                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
                         victim->skeleton.joints[i].velocity += relative * damagemult * 40;
                     }
-                    //victim->DoDamage(1000);
                     victim->damage = victim->damagetolerance;
                     victim->permanentdamage = victim->damagetolerance - 1;
                     bool doslice;
                     doslice = 0;
-                    if (weaponactive != -1 || creature == wolftype)doslice = 1;
-                    if (creature == rabbittype && weaponactive != -1)if (weapons[weaponids[0]].getType() == staff)doslice = 0;
+                    if (weaponactive != -1 || creature == wolftype)
+                        doslice = 1;
+                    if (creature == rabbittype && weaponactive != -1)
+                        if (weapons[weaponids[0]].getType() == staff)
+                            doslice = 0;
                     if (doslice) {
                         if (weaponactive != -1) {
                             victim->DoBloodBig(200, 225);
                             emit_sound_at(knifeslicesound, victim->coords);
-                            if (bloodtoggle)weapons[weaponids[weaponactive]].bloody = 2;
+                            if (bloodtoggle)
+                                weapons[weaponids[weaponactive]].bloody = 2;
                             weapons[weaponids[weaponactive]].blooddrip += 5;
                         }
 
@@ -3022,20 +3486,14 @@ void    Person::DoAnimations()
                 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
                     if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
                         escapednum = 0;
-                        if (animTarget == knifefollowanim)victim->DoBloodBig(200, 210);
+                        if (animTarget == knifefollowanim)
+                            victim->DoBloodBig(200, 210);
                         if (animTarget == knifesneakattackanim) {
-                            /*victim->DoBloodBig(200,195);
-                            XYZ bloodvel;
-                            bloodvel=0;
-                            bloodvel.z=20;
-                            bloodvel.y=5;
-                            bloodvel=DoRotation(bloodvel,((float)(Random()%100))/4,yaw+((float)(Random()%100))/4,0)*scale;
-                            Sprite::MakeSprite(bloodsprite, DoRotation(skeleton.joints[skeleton.jointlabels[neck]].position,0,yaw,0)*scale+coords,bloodvel, 1,1,1, .05, 1);
-                            */
                             XYZ footvel, footpoint;
                             footvel = 0;
                             footpoint = weapons[weaponids[0]].tippoint;
-                            if (bloodtoggle)Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
+                            if (bloodtoggle)
+                                Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
                             footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
@@ -3049,7 +3507,8 @@ void      Person::DoAnimations()
                             XYZ footvel, footpoint;
                             footvel = 0;
                             footpoint = weapons[weaponids[0]].tippoint;
-                            if (bloodtoggle)Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
+                            if (bloodtoggle)
+                                Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
                             footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
@@ -3060,7 +3519,8 @@ void      Person::DoAnimations()
                         victim->bloodloss += 10000;
                         victim->velocity = 0;
                         emit_sound_at(fleshstabsound, victim->coords);
-                        if (bloodtoggle)weapons[weaponids[weaponactive]].bloody = 2;
+                        if (bloodtoggle)
+                            weapons[weaponids[weaponactive]].bloody = 2;
                         weapons[weaponids[weaponactive]].blooddrip += 5;
                     }
                 }
@@ -3068,24 +3528,26 @@ void    Person::DoAnimations()
                 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 6) {
                     escapednum = 0;
                     victim->velocity = 0;
-                    for (i = 0; i < victim->skeleton.num_joints; i++) {
+                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
                         victim->skeleton.joints[i].velocity = 0;
                     }
                     if (animTarget == knifefollowanim) {
                         victim->RagDoll(0);
-                        for (i = 0; i < victim->skeleton.num_joints; i++) {
+                        for (int i = 0; i < victim->skeleton.num_joints; i++) {
                             victim->skeleton.joints[i].velocity = 0;
                         }
                     }
                     if (weaponactive != -1 && animation[victim->animTarget].attack != reversal) {
                         emit_sound_at(fleshstabremovesound, victim->coords);
-                        if (bloodtoggle)weapons[weaponids[weaponactive]].bloody = 2;
+                        if (bloodtoggle)
+                            weapons[weaponids[weaponactive]].bloody = 2;
                         weapons[weaponids[weaponactive]].blooddrip += 5;
 
                         XYZ footvel, footpoint;
                         footvel = 0;
                         footpoint = weapons[weaponids[0]].tippoint;
-                        if (bloodtoggle)Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
+                        if (bloodtoggle)
+                            Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
                         footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
@@ -3103,7 +3565,8 @@ void      Person::DoAnimations()
                         XYZ footvel, footpoint;
                         footvel = 0;
                         footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
-                        if (bloodtoggle)Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
+                        if (bloodtoggle)
+                            Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
                         footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
@@ -3114,7 +3577,8 @@ void      Person::DoAnimations()
                         victim->bloodloss += 10000;
                         victim->velocity = 0;
                         emit_sound_at(fleshstabsound, victim->coords);
-                        if (bloodtoggle)weapons[weaponids[weaponactive]].bloody = 2;
+                        if (bloodtoggle)
+                            weapons[weaponids[weaponactive]].bloody = 2;
                         weapons[weaponids[weaponactive]].blooddrip += 5;
                     }
                 }
@@ -3122,18 +3586,20 @@ void    Person::DoAnimations()
                 if (hasvictim && animTarget == swordsneakattackanim && animation[animTarget].label[frameCurrent] == 6) {
                     escapednum = 0;
                     victim->velocity = 0;
-                    for (i = 0; i < victim->skeleton.num_joints; i++) {
+                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
                         victim->skeleton.joints[i].velocity = 0;
                     }
                     if (weaponactive != -1) {
                         emit_sound_at(fleshstabremovesound, victim->coords);
-                        if (bloodtoggle)weapons[weaponids[weaponactive]].bloody = 2;
+                        if (bloodtoggle)
+                            weapons[weaponids[weaponactive]].bloody = 2;
                         weapons[weaponids[weaponactive]].blooddrip += 5;
 
                         XYZ footvel, footpoint;
                         footvel = 0;
                         footpoint = weapons[weaponids[0]].tippoint;
-                        if (bloodtoggle)Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
+                        if (bloodtoggle)
+                            Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
                         footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
@@ -3144,7 +3610,8 @@ void      Person::DoAnimations()
 
                 if (animTarget == sweepreversalanim && animation[animTarget].label[frameCurrent] == 7) {
                     escapednum = 0;
-                    if (id == 0)camerashake += .4;
+                    if (id == 0)
+                        camerashake += .4;
                     if (Random() % 2) {
                         victim->spurt = 1;
                         DoBlood(.2, 240);
@@ -3156,13 +3623,17 @@ void    Person::DoAnimations()
                     }
                     bool doslice;
                     doslice = 0;
-                    if (weaponactive != -1 || creature == wolftype)doslice = 1;
-                    if (creature == rabbittype && weaponactive != -1)if (weapons[weaponids[0]].getType() == staff)doslice = 0;
+                    if (weaponactive != -1 || creature == wolftype)
+                        doslice = 1;
+                    if (creature == rabbittype && weaponactive != -1)
+                        if (weapons[weaponids[0]].getType() == staff)
+                            doslice = 0;
                     if (doslice) {
                         if (weaponactive != -1) {
                             victim->DoBloodBig(2 / victim->armorhead, 225);
                             emit_sound_at(knifeslicesound, victim->coords);
-                            if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)weapons[weaponids[weaponactive]].bloody = 1;
+                            if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
+                                weapons[weaponids[weaponactive]].bloody = 1;
                             weapons[weaponids[weaponactive]].blooddrip += 3;
                         }
                         if (weaponactive == -1 && creature == wolftype) {
@@ -3177,18 +3648,18 @@ void    Person::DoAnimations()
                     victim->Puff(neck);
 
                     XYZ relative;
-                    //relative=victim->coords-oldcoords;
                     relative = facing * -1;
                     relative.y = 0;
                     Normalise(&relative);
                     relative = DoRotation(relative, 0, 90, 0);
                     relative.y = .5;
                     Normalise(&relative);
-                    for (i = 0; i < victim->skeleton.num_joints; i++) {
+                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
                         victim->skeleton.joints[i].velocity += relative * damagemult * 20;
                     }
-                    victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 200;
-                    if (victim->damage < victim->damagetolerance - 100)victim->velocity = relative * 200;
+                    victim->jointVel(head) += relative * damagemult * 200;
+                    if (victim->damage < victim->damagetolerance - 100)
+                        victim->velocity = relative * 200;
                     victim->DoDamage(damagemult * 100 / victim->protectionhead);
                     victim->velocity = 0;
                 }
@@ -3197,17 +3668,16 @@ void    Person::DoAnimations()
                     escapednum = 0;
                     victim->RagDoll(0);
                     XYZ relative;
-                    //relative=victim->coords-oldcoords;
                     relative = facing * -1;
                     relative.y = 0;
                     Normalise(&relative);
                     relative = DoRotation(relative, 0, 90, 0);
                     relative.y = .5;
                     Normalise(&relative);
-                    for (i = 0; i < victim->skeleton.num_joints; i++) {
+                    for (int i = 0; i < victim->skeleton.num_joints; i++) {
                         victim->skeleton.joints[i].velocity += relative * damagemult * 20;
                     }
-                    victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 200;
+                    victim->jointVel(head) += relative * damagemult * 200;
                 }
 
                 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
@@ -3222,8 +3692,8 @@ void      Person::DoAnimations()
                 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;
@@ -3256,7 +3726,8 @@ void      Person::DoAnimations()
                     if (animCurrent == crouchdrawrightanim) {
                         animTarget = getCrouch();
                     }
-                    if (weaponactive == -1)weaponactive = 0;
+                    if (weaponactive == -1)
+                        weaponactive = 0;
                     else if (weaponactive == 0) {
                         weaponactive = -1;
                         if (num_weapons == 2) {
@@ -3276,8 +3747,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) {
@@ -3316,10 +3787,10 @@ void    Person::DoAnimations()
                         int closest = -1;
                         float closestdist = -1;
                         float distance;
-                        if (numplayers > 1)
-                            for (i = 0; i < numplayers; i++) {
-                                if (id != i && player[i].coords.y < coords.y && !player[i].skeleton.free) {
-                                    distance = distsq(&player[i].coords, &coords);
+                        if (Person::players.size() > 1)
+                            for (unsigned i = 0; i < Person::players.size(); i++) {
+                                if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
+                                    distance = distsq(&Person::players[i]->coords, &coords);
                                     if (closestdist == -1 || distance < closestdist) {
                                         closestdist = distance;
                                         closest = i;
@@ -3327,14 +3798,15 @@ void    Person::DoAnimations()
                                 }
                             }
                         if (closestdist > 0 && closest >= 0 && closestdist < 16) {
-                            victim = &player[closest];
+                            victim = Person::players[closest];
                             animTarget = walljumprightkickanim;
                             frameTarget = 0;
                             XYZ rotatetarget = victim->coords - coords;
                             Normalise(&rotatetarget);
                             yaw = -asin(0 - rotatetarget.x);
                             yaw *= 360 / 6.28;
-                            if (rotatetarget.z < 0)yaw = 180 - yaw;
+                            if (rotatetarget.z < 0)
+                                yaw = 180 - yaw;
                             targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
                             velocity = (victim->coords - coords) * 4;
                             velocity.y += 2;
@@ -3373,10 +3845,10 @@ void    Person::DoAnimations()
                         int closest = -1;
                         float closestdist = -1;
                         float distance;
-                        if (numplayers > 1)
-                            for (i = 0; i < numplayers; i++) {
-                                if (id != i && player[i].coords.y < coords.y && !player[i].skeleton.free) {
-                                    distance = distsq(&player[i].coords, &coords);
+                        if (Person::players.size() > 1)
+                            for (unsigned i = 0; i < Person::players.size(); i++) {
+                                if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
+                                    distance = distsq(&Person::players[i]->coords, &coords);
                                     if (closestdist == -1 || distance < closestdist) {
                                         closestdist = distance;
                                         closest = i;
@@ -3384,14 +3856,15 @@ void    Person::DoAnimations()
                                 }
                             }
                         if (closestdist > 0 && closest >= 0 && closestdist < 16) {
-                            victim = &player[closest];
+                            victim = Person::players[closest];
                             animTarget = walljumpleftkickanim;
                             frameTarget = 0;
                             XYZ rotatetarget = victim->coords - coords;
                             Normalise(&rotatetarget);
                             yaw = -asin(0 - rotatetarget.x);
                             yaw *= 360 / 6.28;
-                            if (rotatetarget.z < 0)yaw = 180 - yaw;
+                            if (rotatetarget.z < 0)
+                                yaw = 180 - yaw;
                             targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
                             velocity = (victim->coords - coords) * 4;
                             velocity.y += 2;
@@ -3421,14 +3894,16 @@ void    Person::DoAnimations()
                     transspeed = 1000000;
                     targetheadyaw += 180;
                     coords -= facing * .7;
-                    if (onterrain)coords.y = terrain.getHeight(coords.x, coords.z);
+                    if (onterrain)
+                        coords.y = terrain.getHeight(coords.x, coords.z);
 
                     lastfeint = 0;
                 }
                 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
                     animTarget = getIdle();
                     frameTarget = 0;
-                    if (onterrain)coords.y = terrain.getHeight(coords.x, coords.z);
+                    if (onterrain)
+                        coords.y = terrain.getHeight(coords.x, coords.z);
 
                     lastfeint = 0;
                 }
@@ -3472,8 +3947,10 @@ void     Person::DoAnimations()
                         targettilt2 = 0;
                         tilt2 = 0;
                     }
-                    if (onterrain)oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
-                    else oldcoords.y = ycoords;
+                    if (onterrain)
+                        oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
+                    else
+                        oldcoords.y = ycoords;
                     currentoffset = coords - oldcoords;
                     targetoffset = 0;
                     coords = oldcoords;
@@ -3487,7 +3964,8 @@ void      Person::DoAnimations()
                 }
                 if (animation[animTarget].attack == reversed) {
                     escapednum++;
-                    if (animTarget == sweepreversedanim)targetyaw += 90;
+                    if (animTarget == sweepreversedanim)
+                        targetyaw += 90;
                     animTarget = backhandspringanim;
                     frameTarget = 2;
                     emit_sound_at(landsound, coords, 128);
@@ -3496,7 +3974,7 @@ void      Person::DoAnimations()
                         animTarget = rollanim;
                         frameTarget = 5;
                         oldcoords = coords;
-                        coords += (DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) + DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 0, yaw, 0)) / 2 * scale;
+                        coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
                         coords.y = oldcoords.y;
                     }
                     if (animCurrent == knifeslashreversedanim) {
@@ -3505,23 +3983,26 @@ void    Person::DoAnimations()
                         targetyaw += 90;
                         yaw += 90;
                         oldcoords = coords;
-                        coords += (DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) + DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 0, yaw, 0)) / 2 * scale;
+                        coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
                         coords.y = oldcoords.y;
                     }
                 }
                 if (wasFlip()) {
                     animTarget = jumpdownanim;
                 }
-                if (wasLanding())animTarget = getIdle();
-                if (wasLandhard())animTarget = getIdle();
+                if (wasLanding())
+                    animTarget = getIdle();
+                if (wasLandhard())
+                    animTarget = getIdle();
                 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
                     animTarget = getIdle();
                     oldcoords = coords;
-                    coords += (DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) + DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 0, yaw, 0)) / 2 * scale;
+                    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;
                     targetoffset.y = coords.y;
-                    if (onterrain)targetoffset.y = terrain.getHeight(coords.x, coords.z);
+                    if (onterrain)
+                        targetoffset.y = terrain.getHeight(coords.x, coords.z);
                     currentoffset = DoRotation(animation[animCurrent].offset * -1, 0, yaw, 0) * scale;
                     currentoffset.y -= (coords.y - targetoffset.y);
                     coords.y = targetoffset.y;
@@ -3537,8 +4018,11 @@ void     Person::DoAnimations()
                     targetyaw = yaw;
                     bool hasstaff;
                     hasstaff = 0;
-                    if (num_weapons > 0)if (weapons[0].getType() == staff)hasstaff = 1;
-                    if (!hasstaff)DoDamage(35);
+                    if (num_weapons > 0)
+                        if (weapons[0].getType() == staff)
+                            hasstaff = 1;
+                    if (!hasstaff)
+                        DoDamage(35);
                     RagDoll(0);
                     lastfeint = 0;
                     rabbitkickragdoll = 1;
@@ -3556,7 +4040,8 @@ void      Person::DoAnimations()
                         escapednum++;
                         animTarget = rollanim;
                         coords += facing;
-                        if (id == 0)pause_sound(whooshsound);
+                        if (id == 0)
+                            pause_sound(whooshsound);
                     }
                     lastfeint = 0;
                 }
@@ -3579,7 +4064,8 @@ void      Person::DoAnimations()
                         escapednum++;
                         animTarget = rollanim;
                         coords += facing * 2;
-                        if (id == 0)pause_sound(whooshsound);
+                        if (id == 0)
+                            pause_sound(whooshsound);
                     }
                     lastfeint = 0;
                 }
@@ -3599,12 +4085,14 @@ void    Person::DoAnimations()
                     lastfeint = 0;
                 }
                 if (animCurrent == spinkickanim && victim->skeleton.free) {
-                    if (creature == rabbittype)animTarget = fightidleanim;
+                    if (creature == rabbittype)
+                        animTarget = fightidleanim;
                 }
             }
             target = 0;
 
-            if (isIdle() && !wasIdle())normalsupdatedelay = 0;
+            if (isIdle() && !wasIdle())
+                normalsupdatedelay = 0;
 
             if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
                 animTarget = jumpdownanim;
@@ -3622,10 +4110,12 @@ void    Person::DoAnimations()
                 if (isRun() && wasRun()) {
                     float tempspeed;
                     tempspeed = velspeed;
-                    if (tempspeed < 10 * speedmult)tempspeed = 10 * speedmult;
+                    if (tempspeed < 10 * speedmult)
+                        tempspeed = 10 * speedmult;
                     target += multiplier * animation[animTarget].speed[frameCurrent] * speed * 1.7 * tempspeed / (speed * 45 * scale);
                 }
-            } else if (transspeed)target += multiplier * transspeed * speed * 2;
+            } else if (transspeed)
+                target += multiplier * transspeed * speed * 2;
             else {
                 if (!isRun() || !wasRun()) {
                     if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
@@ -3635,7 +4125,8 @@ void      Person::DoAnimations()
                 }
             }
 
-            if (animCurrent != animTarget)target = (target + oldtarget) / 2;
+            if (animCurrent != animTarget)
+                target = (target + oldtarget) / 2;
 
             if (target > 1) {
                 frameCurrent = frameTarget;
@@ -3651,64 +4142,71 @@ void    Person::DoAnimations()
             }
             if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
                 //Old rotates
-                for (i = 0; i < skeleton.num_joints; i++) {
+                for (int i = 0; i < skeleton.num_joints; i++) {
                     skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent];
                 }
 
                 skeleton.FindForwards();
 
-                for (i = 0; i < skeleton.num_muscles; i++) {
+                for (int i = 0; i < skeleton.num_muscles; i++) {
                     if (skeleton.muscles[i].visible) {
                         skeleton.FindRotationMuscle(i, animTarget);
                     }
                 }
-                for (i = 0; i < skeleton.num_muscles; i++) {
+                for (int i = 0; i < skeleton.num_muscles; 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;
-                        if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
-                        if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
+                        if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
+                            skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
+                        if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
+                            skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
+                        if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
+                            skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
                     }
                 }
 
                 //New rotates
-                for (i = 0; i < skeleton.num_joints; i++) {
+                for (int i = 0; i < skeleton.num_joints; i++) {
                     skeleton.joints[i].position = animation[animTarget].position[i][frameTarget];
                 }
 
                 skeleton.FindForwards();
 
-                for (i = 0; i < skeleton.num_muscles; i++) {
+                for (int i = 0; i < skeleton.num_muscles; i++) {
                     if (skeleton.muscles[i].visible) {
                         skeleton.FindRotationMuscle(i, animTarget);
                     }
                 }
-                for (i = 0; i < skeleton.num_muscles; i++) {
+                for (int i = 0; i < skeleton.num_muscles; 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;
-                        if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
-                        if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
-                        if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180)skeleton.muscles[i].newrotate3 -= 360;
-                        if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180)skeleton.muscles[i].newrotate3 += 360;
-                        if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180)skeleton.muscles[i].newrotate2 -= 360;
-                        if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180)skeleton.muscles[i].newrotate2 += 360;
-                        if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180)skeleton.muscles[i].newrotate1 -= 360;
-                        if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180)skeleton.muscles[i].newrotate1 += 360;
+                        if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
+                            skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
+                        if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
+                            skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
+                        if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
+                            skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
+                        if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
+                        if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
+                        if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
+                        if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
+                        if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
+                        if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
                     }
                 }
             }
-            if (frameCurrent >= animation[animCurrent].numframes)frameCurrent = animation[animCurrent].numframes - 1;
+            if (frameCurrent >= animation[animCurrent].numframes)
+                frameCurrent = animation[animCurrent].numframes - 1;
 
             oldanimCurrent = animCurrent;
             oldanimTarget = animTarget;
             oldframeTarget = frameTarget;
             oldframeCurrent = frameCurrent;
 
-            for (i = 0; i < skeleton.num_joints; i++) {
+            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);
             }
             offset = currentoffset * (1 - target) + targetoffset * target;
-            for (i = 0; i < skeleton.num_muscles; i++) {
+            for (int i = 0; i < skeleton.num_muscles; 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);
@@ -3718,7 +4216,8 @@ void      Person::DoAnimations()
         }
 
         if (isLanding() && landhard) {
-            if (id == 0)camerashake += .4;
+            if (id == 0)
+                camerashake += .4;
             animTarget = getLandhard();
             frameTarget = 0;
             target = 0;
@@ -3726,10 +4225,13 @@ void    Person::DoAnimations()
             transspeed = 15;
         }
     }
-    //skeleton.DoConstraints();
 }
 
-void   Person::DoStuff()
+/* EFFECT
+ * MONSTER
+ * TODO
+ */
+void Person::DoStuff()
 {
     static XYZ terrainnormal;
     static XYZ flatfacing;
@@ -3752,43 +4254,54 @@ void    Person::DoStuff()
     }
 
     crouchkeydowntime += multiplier;
-    if (!crouchkeydown)crouchkeydowntime = 0;
+    if (!crouchkeydown)
+        crouchkeydowntime = 0;
     jumpkeydowntime += multiplier;
-    if (!jumpkeydown && skeleton.free)jumpkeydowntime = 0;
+    if (!jumpkeydown && skeleton.free)
+        jumpkeydowntime = 0;
 
-    if (hostile || damage > 0 || bloodloss > 0)immobile = 0;
+    if (hostile || damage > 0 || bloodloss > 0)
+        immobile = 0;
 
-    if (isIdle() || isRun())targetoffset = 0;
+    if (isIdle() || isRun())
+        targetoffset = 0;
 
-    if (num_weapons == 1 && weaponactive != -1)weaponstuck = -1;
+    if (num_weapons == 1 && weaponactive != -1)
+        weaponstuck = -1;
 
-    if (id == 0)blooddimamount -= multiplier * .3;
+    if (id == 0)
+        blooddimamount -= multiplier * .3;
     speechdelay -= multiplier;
     texupdatedelay -= multiplier;
     interestdelay -= multiplier;
     flamedelay -= multiplier;
     parriedrecently -= multiplier;
     if (!victim) {
-        victim = this;
+        victim = this->shared_from_this();
         hasvictim = 0;
     }
 
-    if (id == 0)speed = 1.1 * speedmult;
-    else speed = 1.0 * speedmult;
-    if (!skeleton.free)rabbitkickragdoll = 0;
+    if (id == 0)
+        speed = 1.1 * speedmult;
+    else
+        speed = 1.0 * speedmult;
+    if (!skeleton.free)
+        rabbitkickragdoll = 0;
 
     speed *= speedmult;
 
-    if (id != 0 && (creature == rabbittype || difficulty != 2))superruntoggle = 0;
+    if (id != 0 && (creature == rabbittype || difficulty != 2))
+        superruntoggle = 0;
     if (id != 0 && creature == wolftype && difficulty == 2) {
         superruntoggle = 0;
         if (aitype != passivetype) {
             superruntoggle = 1;
-            if (aitype == attacktypecutoff && (player[0].isIdle() || player[0].isCrouch() || player[0].skeleton.free || player[0].animTarget == getupfrombackanim || player[0].animTarget == getupfromfrontanim || player[0].animTarget == sneakanim) && distsq(&coords, &player[0].coords) < 16) {
+            if (aitype == attacktypecutoff && (Person::players[0]->isIdle() || Person::players[0]->isCrouch() || Person::players[0]->skeleton.free || Person::players[0]->animTarget == getupfrombackanim || Person::players[0]->animTarget == getupfromfrontanim || Person::players[0]->animTarget == sneakanim) && distsq(&coords, &Person::players[0]->coords) < 16) {
                 superruntoggle = 0;
             }
         }
-        if (scale < 0.2)superruntoggle = 0;
+        if (scale < 0.2)
+            superruntoggle = 0;
         if (animTarget == wolfrunninganim && !superruntoggle) {
             animTarget = getRun();
             frameTarget = 0;
@@ -3802,10 +4315,9 @@ void     Person::DoStuff()
 
     if (onfire) {
         burnt += multiplier;
-        /*if(aitype!=playercontrolled)*///deathbleeding=5;
-        /*if(aitype!=playercontrolled)*/
         deathbleeding = 1;
-        if (burnt > .6)burnt = .6;
+        if (burnt > .6)
+            burnt = .6;
         OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
 
         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
@@ -3827,20 +4339,26 @@ void    Person::DoStuff()
     while (flamedelay < 0 && onfire) {
         flamedelay += .006;
         howmany = abs(Random() % (skeleton.num_joints));
-        if (!skeleton.free)flatvelocity = (coords - oldcoords) / multiplier / 2; //velocity/2;
-        if (skeleton.free)flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
-        if (!skeleton.free)flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
-        if (skeleton.free)flatfacing = skeleton.joints[howmany].position * scale + coords;
+        if (skeleton.free) {
+            flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
+            flatfacing = skeleton.joints[howmany].position * scale + coords;
+        } else {
+            flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
+            flatvelocity = (coords - oldcoords) / multiplier / 2;
+        }
         Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
     }
 
     while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
         flamedelay += .05;
         howmany = abs(Random() % (skeleton.num_joints));
-        if (!skeleton.free)flatvelocity = (coords - oldcoords) / multiplier / 2; //velocity/2;
-        if (skeleton.free)flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
-        if (!skeleton.free)flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
-        if (skeleton.free)flatfacing = skeleton.joints[howmany].position * scale + coords;
+        if (skeleton.free) {
+            flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
+            flatfacing = skeleton.joints[howmany].position * scale + coords;
+        } else {
+            flatvelocity = (coords - oldcoords) / multiplier / 2;
+            flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
+        }
         Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
     }
 
@@ -3848,7 +4366,8 @@ void      Person::DoStuff()
         bleeding -= multiplier * .3;
         if (bloodtoggle == 2) {
             skeleton.drawmodel.textureptr.bind();
-            if (bleeding <= 0 && (detail != 2 || osx))DoMipmaps();
+            if ((bleeding <= 0) && (detail != 2))
+                DoMipmaps();
         }
     }
 
@@ -3859,17 +4378,16 @@ void    Person::DoStuff()
         if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
             spurt = 0;
             bloodvel = 0;
-            if (!skeleton.free) {
-                bloodvel.z = 5 * neckspurtamount;
-                bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
-            }
             if (skeleton.free) {
                 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
+                bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
+                Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
+            } else {
+                bloodvel.z = 5 * neckspurtamount;
+                bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
+                bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
+                Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
             }
-            if (skeleton.free)bloodvel += DoRotation(skeleton.joints[skeleton.jointlabels[head]].velocity, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
-            if (!skeleton.free)bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
-            if (skeleton.free)Sprite::MakeSprite(bloodsprite, (skeleton.joints[skeleton.jointlabels[neck]].position + (skeleton.joints[skeleton.jointlabels[neck]].position - skeleton.joints[skeleton.jointlabels[head]].position) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
-            if (!skeleton.free)Sprite::MakeSprite(bloodsprite, DoRotation(skeleton.joints[skeleton.jointlabels[neck]].position + (skeleton.joints[skeleton.jointlabels[neck]].position - skeleton.joints[skeleton.jointlabels[head]].position) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
             neckspurtparticledelay = .05;
         }
         if (neckspurtdelay < 0) {
@@ -3878,50 +4396,45 @@ void    Person::DoStuff()
     }
 
     if (deathbleeding > 0 && dead != 2) {
-        if (deathbleeding < 5)bleeddelay -= deathbleeding * multiplier / 4;
-        else bleeddelay -= 5 * multiplier / 4;
+        if (deathbleeding < 5)
+            bleeddelay -= deathbleeding * multiplier / 4;
+        else
+            bleeddelay -= 5 * multiplier / 4;
         if (bleeddelay < 0 && bloodtoggle) {
             bleeddelay = 1;
             XYZ bloodvel;
             if (bloodtoggle) {
                 bloodvel = 0;
-                if (skeleton.free)bloodvel += DoRotation(skeleton.joints[skeleton.jointlabels[abdomen]].velocity, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
-                if (!skeleton.free)bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
-                if (skeleton.free)Sprite::MakeSprite(bloodsprite, skeleton.joints[skeleton.jointlabels[abdomen]].position * scale + coords, bloodvel, 1, 1, 1, .05, 1);
-                if (!skeleton.free)Sprite::MakeSprite(bloodsprite, DoRotation((skeleton.joints[skeleton.jointlabels[abdomen]].position + skeleton.joints[skeleton.jointlabels[abdomen]].position) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
+                if (skeleton.free) {
+                    bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
+                    Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
+                } else {
+                    bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
+                    Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
+                }
             }
         }
         bloodloss += deathbleeding * multiplier * 80;
         deathbleeding -= multiplier * 1.6;
-        //if(id==0)deathbleeding-=multiplier*.2;
-        if (deathbleeding < 0)deathbleeding = 0;
+        if (deathbleeding < 0)
+            deathbleeding = 0;
         if (bloodloss > damagetolerance && animation[animTarget].attack == neutral) {
             if (weaponactive != -1) {
-                weapons[weaponids[0]].owner = -1;
-                weapons[weaponids[0]].velocity = velocity * scale * -.3;
+                weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
                 weapons[weaponids[0]].velocity.x += .01;
-                weapons[weaponids[0]].tipvelocity = velocity * scale;
-                weapons[weaponids[0]].missed = 1;
-                weapons[weaponids[0]].hitsomething = 0;
-                weapons[weaponids[0]].freetime = 0;
-                weapons[weaponids[0]].firstfree = 1;
-                weapons[weaponids[0]].physics = 1;
                 num_weapons--;
                 if (num_weapons) {
                     weaponids[0] = weaponids[num_weapons];
-                    if (weaponstuck == num_weapons)weaponstuck = 0;
+                    if (weaponstuck == num_weapons)
+                        weaponstuck = 0;
                 }
                 weaponactive = -1;
-                for (i = 0; i < numplayers; i++) {
-                    player[i].wentforweapon = 0;
+                for (unsigned i = 0; i < Person::players.size(); i++) {
+                    Person::players[i]->wentforweapon = 0;
                 }
 
                 if (id == 0) {
-                    flashamount = .5;
-                    flashr = 1;
-                    flashg = 0;
-                    flashb = 0;
-                    flashdelay = 0;
+                    Game::flash(.5, 0);
                 }
             }
 
@@ -3930,7 +4443,7 @@ void      Person::DoStuff()
             }
             dead = 2;
             if (animTarget == knifefollowedanim && !skeleton.free) {
-                for (i = 0; i < skeleton.num_joints; i++) {
+                for (int i = 0; i < skeleton.num_joints; i++) {
                     skeleton.joints[i].velocity = 0;
                     skeleton.joints[i].velocity.y = -2;
                 }
@@ -3971,33 +4484,39 @@ void    Person::DoStuff()
             endy = skeleton.skinsize - 1;
             bleeding = 0;
         }
-        if (endx < startx)endx = startx;
-        if (endy < starty)endy = starty;
+        if (endx < startx)
+            endx = startx;
+        if (endy < starty)
+            endy = starty;
 
         for (i = startx; i < endx; i++) {
             for (j = starty; j < endy; j++) {
                 if (Random() % 2 == 0) {
                     color = Random() % 85 + 170;
-                    if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
+                    if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
+                        skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
                     skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
                     skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
                 }
             }
         }
-        if (!osx && detail > 1) {
+        if (detail > 1) {
             skeleton.drawmodel.textureptr.bind();
             DoMipmaps();
         }
 
-        if (!skeleton.free) {
-            bleedy -= 4 / realtexdetail;
-            if (detail == 2)bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
-            else bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
-        }
         if (skeleton.free) {
             bleedx += 4 * direction / realtexdetail;
-            if (detail == 2)bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
-            else bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
+            if (detail == 2)
+                bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
+            else
+                bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
+        } else {
+            bleedy -= 4 / realtexdetail;
+            if (detail == 2)
+                bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
+            else
+                bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
         }
     }
 
@@ -4092,11 +4611,15 @@ void    Person::DoStuff()
             if (environment == snowyenvironment) {
                 XYZ footpoint;
                 XYZ footvel;
-                if (!skeleton.free)footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
-                if (skeleton.free)footvel = skeleton.specialforward[0] * -1;
-                if (!skeleton.free)footpoint = DoRotation((skeleton.joints[skeleton.jointlabels[head]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2, 0, yaw, 0) * scale + coords;
-                if (skeleton.free)footpoint = ((skeleton.joints[skeleton.jointlabels[head]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2) * scale + coords;
-                if (animTarget == sleepanim)footvel = DoRotation(footvel, 0, 90, 0);
+                if (skeleton.free) {
+                    footvel = skeleton.specialforward[0] * -1;
+                    footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
+                } else {
+                    footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
+                    footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
+                }
+                if (animTarget == sleepanim)
+                    footvel = DoRotation(footvel, 0, 90, 0);
                 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
             }
         }
@@ -4162,8 +4685,10 @@ void     Person::DoStuff()
         }
         if (!dead) {
             if (creature == rabbittype) {
-                if (howactive < typesleeping)twitchdelay2 -= multiplier * 1.5;
-                else twitchdelay2 -= multiplier * 0.5;
+                if (howactive < typesleeping)
+                    twitchdelay2 -= multiplier * 1.5;
+                else
+                    twitchdelay2 -= multiplier * 0.5;
                 if (howactive <= typesleeping) {
                     if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
                         tailmorphness = 0;
@@ -4230,20 +4755,24 @@ void    Person::DoStuff()
         }
     }
 
-    if (dead != 1)unconscioustime = 0;
+    if (dead != 1)
+        unconscioustime = 0;
 
     if (dead == 1 || howactive == typesleeping) {
         unconscioustime += multiplier;
         //If unconscious, close eyes and mouth
-        if (righthandmorphend != 0)righthandmorphness = 0;
+        if (righthandmorphend != 0)
+            righthandmorphness = 0;
         righthandmorphend = 0;
         targetrighthandmorphness = 1;
 
-        if (lefthandmorphend != 0)lefthandmorphness = 0;
+        if (lefthandmorphend != 0)
+            lefthandmorphness = 0;
         lefthandmorphend = 0;
         targetlefthandmorphness = 1;
 
-        if (headmorphend != 3 && headmorphend != 5)headmorphness = 0;
+        if (headmorphend != 3 && headmorphend != 5)
+            headmorphness = 0;
         headmorphend = 3;
         targetheadmorphness = 1;
     }
@@ -4269,21 +4798,25 @@ void    Person::DoStuff()
 
     if (dead == 2 || howactive > typesleeping) {
         //If dead, open mouth and hands
-        if (righthandmorphend != 0)righthandmorphness = 0;
+        if (righthandmorphend != 0)
+            righthandmorphness = 0;
         righthandmorphend = 0;
         targetrighthandmorphness = 1;
 
-        if (lefthandmorphend != 0)lefthandmorphness = 0;
+        if (lefthandmorphend != 0)
+            lefthandmorphness = 0;
         lefthandmorphend = 0;
         targetlefthandmorphness = 1;
 
-        if (headmorphend != 2)headmorphness = 0;
+        if (headmorphend != 2)
+            headmorphness = 0;
         headmorphend = 2;
         targetheadmorphness = 1;
     }
 
     if (stunned > 0 && !dead && headmorphend != 2) {
-        if (headmorphend != 4)headmorphness = 0;
+        if (headmorphend != 4)
+            headmorphness = 0;
         headmorphend = 4;
         targetheadmorphness = 1;
     }
@@ -4300,23 +4833,17 @@ void    Person::DoStuff()
         RagDoll(0);
 
         if (weaponactive != -1) {
-            weapons[weaponids[0]].owner = -1;
-            weapons[weaponids[0]].velocity = velocity * scale * -.3;
+            weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
             weapons[weaponids[0]].velocity.x += .01;
-            weapons[weaponids[0]].tipvelocity = velocity * scale;
-            weapons[weaponids[0]].missed = 1;
-            weapons[weaponids[0]].hitsomething = 0;
-            weapons[weaponids[0]].freetime = 0;
-            weapons[weaponids[0]].firstfree = 1;
-            weapons[weaponids[0]].physics = 1;
             num_weapons--;
             if (num_weapons) {
                 weaponids[0] = weaponids[num_weapons];
-                if (weaponstuck == num_weapons)weaponstuck = 0;
+                if (weaponstuck == num_weapons)
+                    weaponstuck = 0;
             }
             weaponactive = -1;
-            for (i = 0; i < numplayers; i++) {
-                player[i].wentforweapon = 0;
+            for (unsigned i = 0; i < Person::players.size(); i++) {
+                Person::players[i]->wentforweapon = 0;
             }
         }
 
@@ -4330,17 +4857,20 @@ void    Person::DoStuff()
         damage += 20;
     }
 
-    //if(dead)damage-=multiplier/4;
-    if (!dead)damage -= multiplier * 13;
-    //if(!dead&&deathbleeding<=0&&id==0)bloodloss-=multiplier*4;
-    if (!dead)permanentdamage -= multiplier * 4;
+    if (!dead)
+        damage -= multiplier * 13;
+    if (!dead)
+        permanentdamage -= multiplier * 4;
     if (isIdle() || isCrouch()) {
-        if (!dead)permanentdamage -= multiplier * 4;
-        //if(!dead&&deathbleeding<=0&&id==0)bloodloss-=multiplier*4;
+        if (!dead)
+            permanentdamage -= multiplier * 4;
     }
-    if (damage < 0)damage = 0;
-    if (permanentdamage < 0)permanentdamage = 0;
-    if (superpermanentdamage < 0)superpermanentdamage = 0;
+    if (damage < 0)
+        damage = 0;
+    if (permanentdamage < 0)
+        permanentdamage = 0;
+    if (superpermanentdamage < 0)
+        superpermanentdamage = 0;
     if (permanentdamage < superpermanentdamage) {
         permanentdamage = superpermanentdamage;
     }
@@ -4351,7 +4881,7 @@ void      Person::DoStuff()
         dead = 0;
         skeleton.free = 1;
         damage -= 20;
-        for (i = 0; i < skeleton.num_joints; i++) {
+        for (int i = 0; i < skeleton.num_joints; i++) {
             skeleton.joints[i].velocity = 0;
         }
     }
@@ -4359,23 +4889,17 @@ void    Person::DoStuff()
         DoBlood(1, 255);
 
         if (weaponactive != -1) {
-            weapons[weaponids[0]].owner = -1;
-            weapons[weaponids[0]].velocity = velocity * scale * -.3;
+            weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
             weapons[weaponids[0]].velocity.x += .01;
-            weapons[weaponids[0]].tipvelocity = velocity * scale;
-            weapons[weaponids[0]].missed = 1;
-            weapons[weaponids[0]].hitsomething = 0;
-            weapons[weaponids[0]].freetime = 0;
-            weapons[weaponids[0]].firstfree = 1;
-            weapons[weaponids[0]].physics = 1;
             num_weapons--;
             if (num_weapons) {
                 weaponids[0] = weaponids[num_weapons];
-                if (weaponstuck == num_weapons)weaponstuck = 0;
+                if (weaponstuck == num_weapons)
+                    weaponstuck = 0;
             }
             weaponactive = -1;
-            for (i = 0; i < numplayers; i++) {
-                player[i].wentforweapon = 0;
+            for (unsigned i = 0; i < Person::players.size(); i++) {
+                Person::players[i]->wentforweapon = 0;
             }
         }
 
@@ -4399,20 +4923,24 @@ void    Person::DoStuff()
     }
 
     if (skeleton.free == 1) {
-        if (id == 0)pause_sound(whooshsound);
+        if (id == 0)
+            pause_sound(whooshsound);
 
         if (!dead) {
             //If knocked over, open hands and close mouth
-            if (righthandmorphend != 0)righthandmorphness = 0;
+            if (righthandmorphend != 0)
+                righthandmorphness = 0;
             righthandmorphend = 0;
             targetrighthandmorphness = 1;
 
-            if (lefthandmorphend != 0)lefthandmorphness = 0;
+            if (lefthandmorphend != 0)
+                lefthandmorphness = 0;
             lefthandmorphend = 0;
             targetlefthandmorphness = 1;
 
             if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
-                if (headmorphend != 0)headmorphness = 0;
+                if (headmorphend != 0)
+                    headmorphness = 0;
                 headmorphend = 0;
                 targetheadmorphness = 1;
             }
@@ -4438,9 +4966,8 @@ void      Person::DoStuff()
         }
         average /= multiplier;
 
-        //velocity=skeleton.joints[skeleton.jointlabels[groin]].velocity*scale;
         velocity = 0;
-        for (i = 0; i < skeleton.num_joints; i++) {
+        for (int i = 0; i < skeleton.num_joints; i++) {
             velocity += skeleton.joints[i].velocity * scale;
         }
         velocity /= skeleton.num_joints;
@@ -4453,14 +4980,15 @@ void    Person::DoStuff()
             skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
             if (skeleton.longdead > 2000) {
                 if (skeleton.longdead > 6000) {
-                    if (id == 0)pause_sound(whooshsound);
+                    if (id == 0)
+                        pause_sound(whooshsound);
                     skeleton.free = 3;
                     DrawSkeleton();
                     skeleton.free = 2;
                 }
                 if (dead == 2 && bloodloss < damagetolerance) {
                     XYZ headpoint;
-                    headpoint = (skeleton.joints[skeleton.jointlabels[head]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2 * scale + coords;
+                    headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
                     DoBlood(1, 255);
                     if (bloodtoggle && !bled) {
                         terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
@@ -4478,8 +5006,9 @@ void      Person::DoStuff()
                 }
                 if (dead == 2 && bloodloss >= damagetolerance) {
                     XYZ headpoint;
-                    headpoint = (skeleton.joints[skeleton.jointlabels[abdomen]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2 * scale + coords;
-                    if (bleeding <= 0)DoBlood(1, 255);
+                    headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
+                    if (bleeding <= 0)
+                        DoBlood(1, 255);
                     if (bloodtoggle && !bled) {
                         terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
                     }
@@ -4503,13 +5032,16 @@ void    Person::DoStuff()
             startpoint = coords;
             endpoint = coords;
             endpoint.y -= .7;
-            if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)canrecover = 0;
-            if (velocity.y < -30)canrecover = 0;
+            if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
+                canrecover = 0;
+            if (velocity.y < -30)
+                canrecover = 0;
             for (i = 0; i < objects.numobjects; i++) {
                 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
                     colviewer = startpoint;
                     coltarget = endpoint;
-                    if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)canrecover = 0;
+                    if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
+                        canrecover = 0;
                 }
             }
             if (canrecover) {
@@ -4517,28 +5049,28 @@ void    Person::DoStuff()
                 XYZ middle;
                 middle = 0;
 
-                terrainnormal = skeleton.joints[skeleton.jointlabels[groin]].position - skeleton.joints[skeleton.jointlabels[abdomen]].position;
-                if (skeleton.joints[skeleton.jointlabels[groin]].locked && skeleton.joints[skeleton.jointlabels[abdomen]].locked) {
-                    terrainnormal = skeleton.joints[skeleton.jointlabels[groin]].position - skeleton.joints[skeleton.jointlabels[abdomen]].position;
-                    middle = (skeleton.joints[skeleton.jointlabels[groin]].position + skeleton.joints[skeleton.jointlabels[abdomen]].position) / 2;
+                terrainnormal = jointPos(groin) - jointPos(abdomen);
+                if (joint(groin).locked && joint(abdomen).locked) {
+                    terrainnormal = jointPos(groin) - jointPos(abdomen);
+                    middle = (jointPos(groin) + jointPos(abdomen)) / 2;
                 }
-                if (skeleton.joints[skeleton.jointlabels[abdomen]].locked && skeleton.joints[skeleton.jointlabels[neck]].locked) {
-                    terrainnormal = skeleton.joints[skeleton.jointlabels[abdomen]].position - skeleton.joints[skeleton.jointlabels[neck]].position;
-                    middle = (skeleton.joints[skeleton.jointlabels[neck]].position + skeleton.joints[skeleton.jointlabels[abdomen]].position) / 2;
+                if (joint(abdomen).locked && joint(neck).locked) {
+                    terrainnormal = jointPos(abdomen) - jointPos(neck);
+                    middle = (jointPos(neck) + jointPos(abdomen)) / 2;
                 }
-                if (skeleton.joints[skeleton.jointlabels[groin]].locked && skeleton.joints[skeleton.jointlabels[neck]].locked) {
-                    terrainnormal = skeleton.joints[skeleton.jointlabels[groin]].position - skeleton.joints[skeleton.jointlabels[neck]].position;
-                    middle = (skeleton.joints[skeleton.jointlabels[groin]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2;
+                if (joint(groin).locked && joint(neck).locked) {
+                    terrainnormal = jointPos(groin) - jointPos(neck);
+                    middle = (jointPos(groin) + jointPos(neck)) / 2;
                 }
                 Normalise(&terrainnormal);
 
                 targetyaw = -asin(0 - terrainnormal.x);
                 targetyaw *= 360 / 6.28;
-                if (terrainnormal.z < 0)targetyaw = 180 - targetyaw;
+                if (terrainnormal.z < 0)
+                    targetyaw = 180 - targetyaw;
                 yaw = targetyaw;
 
                 frameTarget = 0;
-                //     frameTarget=2;
                 animTarget = flipanim;
                 crouchtogglekeydown = 1;
                 target = 0;
@@ -4548,11 +5080,8 @@ void     Person::DoStuff()
                 animCurrent = tempanim;
                 frameCurrent = 0;
                 target = 0;
-                //tilt2=targettilt2;
 
-                //if(middle.y>0)targetoffset.y=middle.y+1;
-
-                for (i = 0; i < skeleton.num_joints; i++) {
+                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);
                 }
@@ -4562,30 +5091,32 @@ void    Person::DoStuff()
         if (findLength(&average) < 10 && !dead && skeleton.free) {
             skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
             if (skeleton.longdead > (damage + 500) * 1.5) {
-                if (id == 0)pause_sound(whooshsound);
+                if (id == 0)
+                    pause_sound(whooshsound);
                 skeleton.free = 0;
                 velocity = 0;
                 XYZ middle;
                 middle = 0;
 
-                terrainnormal = skeleton.joints[skeleton.jointlabels[groin]].position - skeleton.joints[skeleton.jointlabels[abdomen]].position;
-                if (skeleton.joints[skeleton.jointlabels[groin]].locked && skeleton.joints[skeleton.jointlabels[abdomen]].locked) {
-                    terrainnormal = skeleton.joints[skeleton.jointlabels[groin]].position - skeleton.joints[skeleton.jointlabels[abdomen]].position;
-                    middle = (skeleton.joints[skeleton.jointlabels[groin]].position + skeleton.joints[skeleton.jointlabels[abdomen]].position) / 2;
+                terrainnormal = jointPos(groin) - jointPos(abdomen);
+                if (joint(groin).locked && joint(abdomen).locked) {
+                    terrainnormal = jointPos(groin) - jointPos(abdomen);
+                    middle = (jointPos(groin) + jointPos(abdomen)) / 2;
                 }
-                if (skeleton.joints[skeleton.jointlabels[abdomen]].locked && skeleton.joints[skeleton.jointlabels[neck]].locked) {
-                    terrainnormal = skeleton.joints[skeleton.jointlabels[abdomen]].position - skeleton.joints[skeleton.jointlabels[neck]].position;
-                    middle = (skeleton.joints[skeleton.jointlabels[neck]].position + skeleton.joints[skeleton.jointlabels[abdomen]].position) / 2;
+                if (joint(abdomen).locked && joint(neck).locked) {
+                    terrainnormal = jointPos(abdomen) - jointPos(neck);
+                    middle = (jointPos(neck) + jointPos(abdomen)) / 2;
                 }
-                if (skeleton.joints[skeleton.jointlabels[groin]].locked && skeleton.joints[skeleton.jointlabels[neck]].locked) {
-                    terrainnormal = skeleton.joints[skeleton.jointlabels[groin]].position - skeleton.joints[skeleton.jointlabels[neck]].position;
-                    middle = (skeleton.joints[skeleton.jointlabels[groin]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2;
+                if (joint(groin).locked && joint(neck).locked) {
+                    terrainnormal = jointPos(groin) - jointPos(neck);
+                    middle = (jointPos(groin) + jointPos(neck)) / 2;
                 }
                 Normalise(&terrainnormal);
 
                 targetyaw = -asin(0 - terrainnormal.x);
                 targetyaw *= 360 / 6.28;
-                if (terrainnormal.z < 0)targetyaw = 180 - targetyaw;
+                if (terrainnormal.z < 0)
+                    targetyaw = 180 - targetyaw;
                 yaw = targetyaw;
 
                 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
@@ -4611,13 +5142,17 @@ void    Person::DoStuff()
                     if (id == 0) {
                         if (rightkeydown) {
                             targetyaw -= 90;
-                            if (forwardkeydown)targetyaw += 45;
-                            if (backkeydown)targetyaw -= 45;
+                            if (forwardkeydown)
+                                targetyaw += 45;
+                            if (backkeydown)
+                                targetyaw -= 45;
                         }
                         if (leftkeydown) {
                             targetyaw += 90;
-                            if (forwardkeydown)targetyaw -= 45;
-                            if (backkeydown)targetyaw += 45;
+                            if (forwardkeydown)
+                                targetyaw -= 45;
+                            if (backkeydown)
+                                targetyaw += 45;
                         }
                         if (backkeydown) {
                             if ( !leftkeydown && !rightkeydown)
@@ -4627,15 +5162,17 @@ void    Person::DoStuff()
                     }
                 }
 
-                if (abs(targettilt2) > 50)targettilt2 = 0;
+                if (abs(targettilt2) > 50)
+                    targettilt2 = 0;
                 animCurrent = tempanim;
                 frameCurrent = 0;
                 target = 0;
                 tilt2 = targettilt2;
 
-                if (middle.y > 0 && animTarget != rollanim)targetoffset.y = middle.y + 1;
+                if (middle.y > 0 && animTarget != rollanim)
+                    targetoffset.y = middle.y + 1;
 
-                for (i = 0; i < skeleton.num_joints; i++) {
+                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);
                 }
@@ -4644,7 +5181,9 @@ void      Person::DoStuff()
 
         bool hasstaff;
         hasstaff = 0;
-        if (num_weapons > 0)if (weapons[0].getType() == staff)hasstaff = 1;
+        if (num_weapons > 0)
+            if (weapons[0].getType() == staff)
+                hasstaff = 1;
         if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
             if (velocity.y > -30) {
                 XYZ tempvelocity;
@@ -4652,7 +5191,8 @@ void      Person::DoStuff()
                 Normalise(&tempvelocity);
                 targetyaw = -asin(0 - tempvelocity.x);
                 targetyaw *= 360 / 6.28;
-                if (velocity.z < 0)targetyaw = 180 - targetyaw;
+                if (velocity.z < 0)
+                    targetyaw = 180 - targetyaw;
                 //targetyaw+=180;
 
                 skeleton.free = 0;
@@ -4681,7 +5221,8 @@ void      Person::DoStuff()
                 targettilt2 = 0;
             }
         }
-        if (skeleton.freefall == 0)freefall = 0;
+        if (skeleton.freefall == 0)
+            freefall = 0;
 
     }
 
@@ -4723,15 +5264,14 @@ 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;
-                            if (environment == grassyenvironment)howmany = findLength(&velocity) * 4;
-                            if (environment == snowyenvironment)howmany = findLength(&velocity) * 2;
+                            if (environment == grassyenvironment)
+                                howmany = findLength(&velocity) * 4;
+                            if (environment == snowyenvironment)
+                                howmany = findLength(&velocity) * 2;
                             if (detail == 2)
                                 if (environment != desertenvironment)
                                     for (j = 0; j < howmany; j++) {
@@ -4768,7 +5308,8 @@ void      Person::DoStuff()
                     }
                 XYZ tempcoord;
                 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
-                    if (objects.pitch[i] == 0)tempcoord = coords;
+                    if (objects.pitch[i] == 0)
+                        tempcoord = coords;
                     else {
                         tempcoord = coords - objects.position[i];
                         tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
@@ -4783,15 +5324,14 @@ 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;
-                            if (environment == grassyenvironment)howmany = findLength(&velocity) * 4;
-                            if (environment == snowyenvironment)howmany = findLength(&velocity) * 2;
+                            if (environment == grassyenvironment)
+                                howmany = findLength(&velocity) * 4;
+                            if (environment == snowyenvironment)
+                                howmany = findLength(&velocity) * 2;
                             if (detail == 2)
                                 if (environment != desertenvironment)
                                     for (j = 0; j < howmany; j++) {
@@ -4832,21 +5372,28 @@ void    Person::DoStuff()
     if (!skeleton.free) {
         bool play;
         play = 0;
-        if ((stunned > 0 || surprised > 0) && numplayers > 2 && aitype != passivetype)play = 1;
+        if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
+            play = 1;
         if (hasvictim)
-            if (aitype != passivetype && victim->skeleton.free && !victim->dead)play = 1;
-        if (tutoriallevel == 1 && id != 0)play = 0;
+            if (aitype != passivetype && victim->skeleton.free && !victim->dead)
+                play = 1;
+        if (tutoriallevel == 1 && id != 0)
+            play = 0;
         if (play && aitype != playercontrolled) {
             int whichsound = -1;
             i = abs(Random() % 4);
             if (speechdelay <= 0) {
                 if (creature == rabbittype) {
-                    if (i == 0)whichsound = rabbitchitter;
-                    if (i == 1)whichsound = rabbitchitter2;
+                    if (i == 0)
+                        whichsound = rabbitchitter;
+                    if (i == 1)
+                        whichsound = rabbitchitter2;
                 }
                 if (creature == wolftype) {
-                    if (i == 0)whichsound = growlsound;
-                    if (i == 1)whichsound = growl2sound;
+                    if (i == 0)
+                        whichsound = growlsound;
+                    if (i == 1)
+                        whichsound = growl2sound;
                 }
             }
             speechdelay = .3;
@@ -4856,11 +5403,15 @@ void    Person::DoStuff()
             }
         }
 
-        if (animTarget == staggerbackhighanim)staggerdelay = 1;
-        if (animTarget == staggerbackhardanim)staggerdelay = 1;
+        if (animTarget == staggerbackhighanim)
+            staggerdelay = 1;
+        if (animTarget == staggerbackhardanim)
+            staggerdelay = 1;
         staggerdelay -= multiplier;
-        if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)hasvictim = 1;
-        if (velocity.y < -30 && animTarget == jumpdownanim)RagDoll(0);
+        if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
+            hasvictim = 1;
+        if (velocity.y < -30 && animTarget == jumpdownanim)
+            RagDoll(0);
         if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
             animTarget = getIdle();
             frameTarget = 0;
@@ -4926,7 +5477,7 @@ void      Person::DoStuff()
             }
         }
 
-        if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim || animTarget == blockhighleftanim) {
+        if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
             //close hands and mouth
             if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
                 righthandmorphness = 0;
@@ -4971,7 +5522,9 @@ void      Person::DoStuff()
         bool behind;
         behind = 0;
         if (hasvictim) {
-            if (victim != this && !victim->dead && victim->aitype != passivetype && victim->aitype != searchtype && aitype != passivetype && aitype != searchtype && victim->id < numplayers && aitype != passivetype) {
+            if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
+                (victim->aitype != searchtype) && (aitype != passivetype) &&
+                (aitype != searchtype) && (victim->id < Person::players.size())) {
                 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
             }
         }
@@ -5014,34 +5567,46 @@ void    Person::DoStuff()
         Normalise(&facing);
 
         if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
-            if (onterrain)targettilt2 = -facing.y * 20;
-            else targettilt2 = 0;
+            if (onterrain)
+                targettilt2 = -facing.y * 20;
+            else
+                targettilt2 = 0;
         }
         onterrain = 0;
-        if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)targettilt2 = 0;
+        if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
+            targettilt2 = 0;
         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
             flatvelocity = velocity;
             flatvelocity.y = 0;
             flatvelspeed = findLength(&flatvelocity);
             targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
             targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
-            if (velocity.y < 0)targettilt2 *= -1;
-            if (velocity.y < 0)targettilt *= -1;
-            if (targettilt > 25)targettilt = 25;
-            if (targettilt < -25)targettilt = -25;
-        }
-
-        if (targettilt2 > 45)targettilt2 = 45;
-        if (targettilt2 < -45)targettilt2 = -45;
-        if (abs(tilt2 - targettilt2) < multiplier * 400)tilt2 = targettilt2;
+            if (velocity.y < 0)
+                targettilt2 *= -1;
+            if (velocity.y < 0)
+                targettilt *= -1;
+            if (targettilt > 25)
+                targettilt = 25;
+            if (targettilt < -25)
+                targettilt = -25;
+        }
+
+        if (targettilt2 > 45)
+            targettilt2 = 45;
+        if (targettilt2 < -45)
+            targettilt2 = -45;
+        if (abs(tilt2 - targettilt2) < multiplier * 400)
+            tilt2 = targettilt2;
         else if (tilt2 > targettilt2) {
             tilt2 -= multiplier * 400;
         } else if (tilt2 < targettilt2) {
             tilt2 += multiplier * 400;
         }
         if (!animation[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
-            if (tilt2 > 25)tilt2 = 25;
-            if (tilt2 < -25)tilt2 = -25;
+            if (tilt2 > 25)
+                tilt2 = 25;
+            if (tilt2 < -25)
+                tilt2 = -25;
         }
 
         if (!isnormal(targettilt) && targettilt) {
@@ -5052,7 +5617,6 @@ void      Person::DoStuff()
         }
 
         //Running velocity
-        //if(!creature==wolftype||animTarget==rabbitkickanim)
         if (animTarget == rabbittackleanim) {
             velocity += facing * multiplier * speed * 700 * scale;
             velspeed = findLength(&velocity);
@@ -5078,7 +5642,8 @@ void      Person::DoStuff()
                 velocity.y += gravity * multiplier * 20;
                 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
                 velspeed = findLength(&velocity);
-                if (velspeed < speed * 30 * scale)velspeed = speed * 30 * scale;
+                if (velspeed < speed * 30 * scale)
+                    velspeed = speed * 30 * scale;
                 velocity = flatfacing * velspeed;
             }
         } else if (isRun()) {
@@ -5118,21 +5683,6 @@ void     Person::DoStuff()
             velocity = flatfacing * velspeed;
         }
 
-
-        /*if(animCurrent==rollanim&&(isCrouch()||isIdle())){
-        velocity+=facing*multiplier*speed*700*scale;
-        velspeed=findLength(&velocity);
-        if(velspeed>speed*25*scale){
-        velocity/=velspeed;
-        velspeed=speed*25*scale;
-        velocity*=velspeed;
-        }
-        velocity.y+=gravity*multiplier*20;
-        ReflectVector(&velocity,terrain.getNormal(coords.x,coords.z));
-        velspeed=findLength(&velocity);
-        velocity=flatfacing*velspeed;
-        }*/
-
         if (animTarget == sneakanim || animTarget == walkanim) {
             velocity += facing * multiplier * speed * 700 * scale;
             velspeed = findLength(&velocity);
@@ -5237,10 +5787,12 @@ void    Person::DoStuff()
             velocity.y += gravity * multiplier;
         }
 
-        if (animTarget != climbanim && animTarget != hanganim && !isWallJump())coords += velocity * multiplier;
+        if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
+            coords += velocity * multiplier;
 
         if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
-            if (isFlip() && animation[animTarget].label[frameTarget] == 7)RagDoll(0);
+            if (isFlip() && animation[animTarget].label[frameTarget] == 7)
+                RagDoll(0);
 
             if (animTarget == jumpupanim) {
                 jumppower = -4;
@@ -5261,15 +5813,13 @@ void    Person::DoStuff()
                 emit_sound_at(landsound, coords, 128.);
 
                 if (id == 0) {
-                    envsound[numenvsounds] = coords;
-                    envsoundvol[numenvsounds] = 16;
-                    envsoundlife[numenvsounds] = .4;
-                    numenvsounds++;
+                    addEnvSound(coords);
                 }
             }
         }
 
-        if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())coords.y += gravity * multiplier * 2;
+        if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
+            coords.y += gravity * multiplier * 2;
         if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
             coords.y = terrain.getHeight(coords.x, coords.z);
             onterrain = 1;
@@ -5281,15 +5831,17 @@ void    Person::DoStuff()
             velocity.y = 0;
             if (velspeed < multiplier * 300 * scale) {
                 velocity = 0;
-            } else velocity -= velocity / velspeed * multiplier * 300 * scale;
+            } else
+                velocity -= velocity / velspeed * multiplier * 300 * scale;
             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 skiddingdelay = 0;
+            } else
+                skiddingdelay = 0;
         }
 
         if (isLandhard()) {
@@ -5297,19 +5849,22 @@ void    Person::DoStuff()
             velocity.y = 0;
             if (velspeed < multiplier * 600 * scale) {
                 velocity = 0;
-            } else velocity -= velocity / velspeed * multiplier * 600 * scale;
+            } else
+                velocity -= velocity / velspeed * multiplier * 600 * scale;
             velocity = 0;
             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 skiddingdelay = 0;
+            } else
+                skiddingdelay = 0;
         }
 
-        if (skiddingdelay < 0)skiddingdelay += multiplier;
+        if (skiddingdelay < 0)
+            skiddingdelay += multiplier;
         if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
             skiddingdelay = -1;
             if (!onterrain || environment == grassyenvironment) {
@@ -5324,7 +5879,8 @@ void      Person::DoStuff()
             Normalise(&terrainnormal);
             targetyaw = -asin(0 - terrainnormal.x);
             targetyaw *= 360 / 6.28;
-            if (terrainnormal.z < 0)targetyaw = 180 - targetyaw;
+            if (terrainnormal.z < 0)
+                targetyaw = 180 - targetyaw;
             targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
         }
 
@@ -5352,6 +5908,52 @@ void     Person::DoStuff()
     }
 }
 
+
+/* EFFECT
+ * inverse kinematics helper function
+ */
+void IKHelper(Person *p, float interp)
+{
+    XYZ point, change, change2;
+    float heightleft, heightright;
+
+    // TODO: implement localToWorld and worldToLocal
+    //       but keep in mind it won't be the same math if player is ragdolled or something
+    //       - localToWorldStanding / worldToLocalStanding (or crouching or...?)
+    //       then comb through code for places where to use it
+
+    // point = localToWorld(jointPos(leftfoot))
+    point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
+    // adjust height of foot
+    heightleft = terrain.getHeight(point.x, point.z) + .04;
+    point.y = heightleft;
+    change = p->jointPos(leftankle) - p->jointPos(leftfoot);
+    change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
+    // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
+    p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
+    // move ankle along with foot
+    p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
+    // average knee pos between old and new pos
+    p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
+
+    // do same as above for right leg
+    point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
+    heightright = terrain.getHeight(point.x, point.z) + .04;
+    point.y = heightright;
+    change = p->jointPos(rightankle) - p->jointPos(rightfoot);
+    change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
+    p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
+    p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
+    p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
+
+    // fix up skeleton now that we've moved body parts?
+    p->skeleton.DoConstraints(&p->coords, &p->scale);
+}
+
+/* EFFECT
+ * MONSTER
+ * TODO: ???
+ */
 int Person::DrawSkeleton()
 {
     int oldplayerdetail;
@@ -5370,9 +5972,12 @@ int Person::DrawSkeleton()
         XYZ terrainlight;
         float terrainheight;
         float distance;
-        if (!isnormal(yaw))yaw = 0;
-        if (!isnormal(tilt))tilt = 0;
-        if (!isnormal(tilt2))tilt2 = 0;
+        if (!isnormal(yaw))
+            yaw = 0;
+        if (!isnormal(tilt))
+            tilt = 0;
+        if (!isnormal(tilt2))
+            tilt2 = 0;
         oldplayerdetail = playerdetail;
         playerdetail = 0;
         if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
@@ -5409,140 +6014,38 @@ int Person::DrawSkeleton()
         static int start, endthing;
         if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
             if (!isSleeping() && !isSitting()) {
-                if (onterrain && ((isIdle() || isCrouch() || isLanding() || isLandhard() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim) && (wasIdle() || wasCrouch() || wasLanding() || wasLandhard() || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim)) && !skeleton.free) {
-                    XYZ point, newpoint, change, change2;
-                    point = DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
-                    heightleft = terrain.getHeight(point.x, point.z) + .04;
-                    point.y = heightleft;
-                    change = skeleton.joints[skeleton.jointlabels[leftankle]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
-                    change2 = skeleton.joints[skeleton.jointlabels[leftknee]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
-                    skeleton.joints[skeleton.jointlabels[leftfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0);
-                    skeleton.joints[skeleton.jointlabels[leftankle]].position = skeleton.joints[skeleton.jointlabels[leftfoot]].position + change;
-                    skeleton.joints[skeleton.jointlabels[leftknee]].position = (skeleton.joints[skeleton.jointlabels[leftfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[leftknee]].position) / 2;
-
-                    point = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 0, yaw, 0) * scale + coords;
-                    heightright = terrain.getHeight(point.x, point.z) + .04;
-                    point.y = heightright;
-                    change = skeleton.joints[skeleton.jointlabels[rightankle]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
-                    change2 = skeleton.joints[skeleton.jointlabels[rightknee]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
-                    skeleton.joints[skeleton.jointlabels[rightfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0);
-                    skeleton.joints[skeleton.jointlabels[rightankle]].position = skeleton.joints[skeleton.jointlabels[rightfoot]].position + change;
-                    skeleton.joints[skeleton.jointlabels[rightknee]].position = (skeleton.joints[skeleton.jointlabels[rightfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[rightknee]].position) / 2;
-                    skeleton.DoConstraints(&coords, &scale);
+                // TODO: give these meaningful names
+                const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
+                                    || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
+                const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
+                                    || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
 
-                    if (creature == wolftype) {
-                        point = DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
-                        heightleft = terrain.getHeight(point.x, point.z) + .04;
-                        point.y = heightleft;
-                        change = skeleton.joints[skeleton.jointlabels[leftankle]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
-                        change2 = skeleton.joints[skeleton.jointlabels[leftknee]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
-                        skeleton.joints[skeleton.jointlabels[leftfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0);
-                        skeleton.joints[skeleton.jointlabels[leftankle]].position = skeleton.joints[skeleton.jointlabels[leftfoot]].position + change;
-                        skeleton.joints[skeleton.jointlabels[leftknee]].position = (skeleton.joints[skeleton.jointlabels[leftfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[leftknee]].position) / 2;
-
-                        point = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 0, yaw, 0) * scale + coords;
-                        heightright = terrain.getHeight(point.x, point.z) + .04;
-                        point.y = heightright;
-                        change = skeleton.joints[skeleton.jointlabels[rightankle]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
-                        change2 = skeleton.joints[skeleton.jointlabels[rightknee]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
-                        skeleton.joints[skeleton.jointlabels[rightfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0);
-                        skeleton.joints[skeleton.jointlabels[rightankle]].position = skeleton.joints[skeleton.jointlabels[rightfoot]].position + change;
-                        skeleton.joints[skeleton.jointlabels[rightknee]].position = (skeleton.joints[skeleton.jointlabels[rightfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[rightknee]].position) / 2;
-                        skeleton.DoConstraints(&coords, &scale);
-                    }
-                }
-                if (onterrain && ((isIdle() || isCrouch() || isLanding() || isLandhard() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim) && !(wasIdle() || wasCrouch() || wasLanding() || wasLandhard() || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim)) && !skeleton.free) {
-                    XYZ point, newpoint, change, change2;
-                    point = DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
-                    heightleft = terrain.getHeight(point.x, point.z) + .04;
-                    point.y = heightleft;
-                    change = skeleton.joints[skeleton.jointlabels[leftankle]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
-                    change2 = skeleton.joints[skeleton.jointlabels[leftknee]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
-                    skeleton.joints[skeleton.jointlabels[leftfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0) * target + skeleton.joints[skeleton.jointlabels[leftfoot]].position * (1 - target);
-                    skeleton.joints[skeleton.jointlabels[leftankle]].position = skeleton.joints[skeleton.jointlabels[leftfoot]].position + change;
-                    skeleton.joints[skeleton.jointlabels[leftknee]].position = (skeleton.joints[skeleton.jointlabels[leftfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[leftknee]].position) / 2;
-
-                    point = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 0, yaw, 0) * scale + coords;
-                    heightright = terrain.getHeight(point.x, point.z) + .04;
-                    point.y = heightright;
-                    change = skeleton.joints[skeleton.jointlabels[rightankle]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
-                    change2 = skeleton.joints[skeleton.jointlabels[rightknee]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
-                    skeleton.joints[skeleton.jointlabels[rightfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0) * target + skeleton.joints[skeleton.jointlabels[rightfoot]].position * (1 - target);
-                    skeleton.joints[skeleton.jointlabels[rightankle]].position = skeleton.joints[skeleton.jointlabels[rightfoot]].position + change;
-                    skeleton.joints[skeleton.jointlabels[rightknee]].position = (skeleton.joints[skeleton.jointlabels[rightfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[rightknee]].position) / 2;
-                    skeleton.DoConstraints(&coords, &scale);
+                if (onterrain && (cond1 && cond2) && !skeleton.free) {
+                    IKHelper(this, 1);
+                    if (creature == wolftype)
+                        IKHelper(this, 1);
+                }
 
-                    if (creature == wolftype) {
-                        point = DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
-                        heightleft = terrain.getHeight(point.x, point.z) + .04;
-                        point.y = heightleft;
-                        change = skeleton.joints[skeleton.jointlabels[leftankle]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
-                        change2 = skeleton.joints[skeleton.jointlabels[leftknee]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
-                        skeleton.joints[skeleton.jointlabels[leftfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0) * target + skeleton.joints[skeleton.jointlabels[leftfoot]].position * (1 - target);
-                        skeleton.joints[skeleton.jointlabels[leftankle]].position = skeleton.joints[skeleton.jointlabels[leftfoot]].position + change;
-                        skeleton.joints[skeleton.jointlabels[leftknee]].position = (skeleton.joints[skeleton.jointlabels[leftfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[leftknee]].position) / 2;
-
-                        point = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 0, yaw, 0) * scale + coords;
-                        heightright = terrain.getHeight(point.x, point.z) + .04;
-                        point.y = heightright;
-                        change = skeleton.joints[skeleton.jointlabels[rightankle]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
-                        change2 = skeleton.joints[skeleton.jointlabels[rightknee]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
-                        skeleton.joints[skeleton.jointlabels[rightfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0) * target + skeleton.joints[skeleton.jointlabels[rightfoot]].position * (1 - target);
-                        skeleton.joints[skeleton.jointlabels[rightankle]].position = skeleton.joints[skeleton.jointlabels[rightfoot]].position + change;
-                        skeleton.joints[skeleton.jointlabels[rightknee]].position = (skeleton.joints[skeleton.jointlabels[rightfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[rightknee]].position) / 2;
-                        skeleton.DoConstraints(&coords, &scale);
-                    }
-                }
-
-                if (onterrain && (!(isIdle() || isCrouch() || isLanding() || isLandhard() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim) && (wasIdle() || wasCrouch() || wasLanding() || wasLandhard() || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim)) && !skeleton.free) {
-                    XYZ point, newpoint, change, change2;
-                    point = DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
-                    heightleft = terrain.getHeight(point.x, point.z) + .04;
-                    point.y = heightleft;
-                    change = skeleton.joints[skeleton.jointlabels[leftankle]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
-                    change2 = skeleton.joints[skeleton.jointlabels[leftknee]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
-                    skeleton.joints[skeleton.jointlabels[leftfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0) * (1 - target) + skeleton.joints[skeleton.jointlabels[leftfoot]].position * target;
-                    skeleton.joints[skeleton.jointlabels[leftankle]].position = skeleton.joints[skeleton.jointlabels[leftfoot]].position + change;
-                    skeleton.joints[skeleton.jointlabels[leftknee]].position = (skeleton.joints[skeleton.jointlabels[leftfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[leftknee]].position) / 2;
-
-                    point = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 0, yaw, 0) * scale + coords;
-                    heightright = terrain.getHeight(point.x, point.z) + .04;
-                    point.y = heightright;
-                    change = skeleton.joints[skeleton.jointlabels[rightankle]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
-                    change2 = skeleton.joints[skeleton.jointlabels[rightknee]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
-                    skeleton.joints[skeleton.jointlabels[rightfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0) * (1 - target) + skeleton.joints[skeleton.jointlabels[rightfoot]].position * target;
-                    skeleton.joints[skeleton.jointlabels[rightankle]].position = skeleton.joints[skeleton.jointlabels[rightfoot]].position + change;
-                    skeleton.joints[skeleton.jointlabels[rightknee]].position = (skeleton.joints[skeleton.jointlabels[rightfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[rightknee]].position) / 2;
-                    skeleton.DoConstraints(&coords, &scale);
+                if (onterrain && (cond1 && !cond2) && !skeleton.free) {
+                    IKHelper(this, target);
+                    if (creature == wolftype)
+                        IKHelper(this, target);
+                }
 
-                    if (creature == wolftype) {
-                        point = DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
-                        heightleft = terrain.getHeight(point.x, point.z) + .04;
-                        point.y = heightleft;
-                        change = skeleton.joints[skeleton.jointlabels[leftankle]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
-                        change2 = skeleton.joints[skeleton.jointlabels[leftknee]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
-                        skeleton.joints[skeleton.jointlabels[leftfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0) * (1 - target) + skeleton.joints[skeleton.jointlabels[leftfoot]].position * target;
-                        skeleton.joints[skeleton.jointlabels[leftankle]].position = skeleton.joints[skeleton.jointlabels[leftfoot]].position + change;
-                        skeleton.joints[skeleton.jointlabels[leftknee]].position = (skeleton.joints[skeleton.jointlabels[leftfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[leftknee]].position) / 2;
-
-                        point = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 0, yaw, 0) * scale + coords;
-                        heightright = terrain.getHeight(point.x, point.z) + .04;
-                        point.y = heightright;
-                        change = skeleton.joints[skeleton.jointlabels[rightankle]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
-                        change2 = skeleton.joints[skeleton.jointlabels[rightknee]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
-                        skeleton.joints[skeleton.jointlabels[rightfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0) * (1 - target) + skeleton.joints[skeleton.jointlabels[rightfoot]].position * target;
-                        skeleton.joints[skeleton.jointlabels[rightankle]].position = skeleton.joints[skeleton.jointlabels[rightfoot]].position + change;
-                        skeleton.joints[skeleton.jointlabels[rightknee]].position = (skeleton.joints[skeleton.jointlabels[rightfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[rightknee]].position) / 2;
-                        skeleton.DoConstraints(&coords, &scale);
-                    }
+                if (onterrain && (!cond1 && cond2) && !skeleton.free) {
+                    IKHelper(this, 1 - target);
+                    if (creature == wolftype)
+                        IKHelper(this, 1 - target);
                 }
             }
+
             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()))
                 DoHead();
             else {
                 targetheadyaw = -targetyaw;
                 targetheadpitch = 0;
-                if (animation[animTarget].attack == 3)targetheadyaw += 180;
+                if (animation[animTarget].attack == 3)
+                    targetheadyaw += 180;
             }
             for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
                 skeleton.drawmodel.vertex[i] = 0;
@@ -5556,43 +6059,51 @@ int Person::DrawSkeleton()
                 skeleton.drawmodelclothes.vertex[i] = 0;
                 skeleton.drawmodelclothes.vertex[i].y = 999;
             }
-            for (i = 0; i < skeleton.num_muscles; i++) {
+            for (int i = 0; i < skeleton.num_muscles; 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)) {
                     morphness = 0;
                     start = 0;
                     endthing = 0;
-                    if (skeleton.muscles[i].parent1->label == righthand || skeleton.muscles[i].parent2->label == righthand) {
+
+                    if (p1 == righthand || p2 == righthand) {
                         morphness = righthandmorphness;
                         start = righthandmorphstart;
                         endthing = righthandmorphend;
                     }
-                    if (skeleton.muscles[i].parent1->label == lefthand || skeleton.muscles[i].parent2->label == lefthand) {
+                    if (p1 == lefthand || p2 == lefthand) {
                         morphness = lefthandmorphness;
                         start = lefthandmorphstart;
                         endthing = lefthandmorphend;
                     }
-                    if (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head) {
+                    if (p1 == head || p2 == head) {
                         morphness = headmorphness;
                         start = headmorphstart;
                         endthing = headmorphend;
                     }
-                    if ((skeleton.muscles[i].parent1->label == neck && skeleton.muscles[i].parent2->label == abdomen) || (skeleton.muscles[i].parent2->label == neck && skeleton.muscles[i].parent1->label == abdomen)) {
+                    if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
                         morphness = chestmorphness;
                         start = chestmorphstart;
                         endthing = chestmorphend;
                     }
-                    if ((skeleton.muscles[i].parent1->label == groin && skeleton.muscles[i].parent2->label == abdomen) || (skeleton.muscles[i].parent2->label == groin && skeleton.muscles[i].parent1->label == abdomen)) {
+                    if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
                         morphness = tailmorphness;
                         start = tailmorphstart;
                         endthing = tailmorphend;
                     }
-                    if (calcrot)skeleton.FindRotationMuscle(i, animTarget);
+                    if (calcrot)
+                        skeleton.FindRotationMuscle(i, animTarget);
                     mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
-                    glMatrixMode(GL_MODELVIEW);                                                        // Select The Modelview Matrix
+                    glMatrixMode(GL_MODELVIEW);
                     glPushMatrix();
                     glLoadIdentity();
-                    if (!skeleton.free)glRotatef(tilt2, 1, 0, 0);
-                    if (!skeleton.free)glRotatef(tilt, 0, 0, 1);
+                    if (!skeleton.free)
+                        glRotatef(tilt2, 1, 0, 0);
+                    if (!skeleton.free)
+                        glRotatef(tilt, 0, 0, 1);
 
 
                     glTranslatef(mid.x, mid.y, mid.z);
@@ -5608,54 +6119,54 @@ int Person::DrawSkeleton()
 
                     if (playerdetail || skeleton.free == 3) {
                         for (j = 0; j < skeleton.muscles[i].numvertices; j++) {
-                            glMatrixMode(GL_MODELVIEW);                                                        // Select The Modelview Matrix
+                            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);
                             glPushMatrix();
-                            if (skeleton.muscles[i].parent1->label == abdomen || skeleton.muscles[i].parent2->label == abdomen)
-                                glTranslatef((skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].x * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].x * morphness)*proportionbody.x,
-                                             (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].y * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].y * morphness)*proportionbody.y,
-                                             (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].z * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].z * morphness)*proportionbody.z);
-                            if (skeleton.muscles[i].parent1->label == lefthand || skeleton.muscles[i].parent1->label == righthand || skeleton.muscles[i].parent1->label == leftwrist || skeleton.muscles[i].parent1->label == rightwrist || skeleton.muscles[i].parent1->label == leftelbow || skeleton.muscles[i].parent1->label == rightelbow || skeleton.muscles[i].parent2->label == leftelbow || skeleton.muscles[i].parent2->label == rightelbow)
-                                glTranslatef((skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].x * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].x * morphness)*proportionarms.x,
-                                             (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].y * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].y * morphness)*proportionarms.y,
-                                             (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].z * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].z * morphness)*proportionarms.z);
-                            if (skeleton.muscles[i].parent1->label == leftfoot || skeleton.muscles[i].parent1->label == rightfoot || skeleton.muscles[i].parent1->label == leftankle || skeleton.muscles[i].parent1->label == rightankle || skeleton.muscles[i].parent1->label == leftknee || skeleton.muscles[i].parent1->label == rightknee || skeleton.muscles[i].parent2->label == leftknee || skeleton.muscles[i].parent2->label == rightknee)
-                                glTranslatef((skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].x * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].x * morphness)*proportionlegs.x,
-                                             (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].y * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].y * morphness)*proportionlegs.y,
-                                             (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].z * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].z * morphness)*proportionlegs.z);
-                            if (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)
-                                glTranslatef((skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].x * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].x * morphness)*proportionhead.x,
-                                             (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].y * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].y * morphness)*proportionhead.y,
-                                             (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].z * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].z * morphness)*proportionhead.z);
+                            if (p1 == abdomen || p2 == abdomen)
+                                glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
+                                             (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
+                                             (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
+                            if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
+                                glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
+                                             (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
+                                             (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
+                            if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
+                                glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
+                                             (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
+                                             (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
+                            if (p1 == head || p2 == head)
+                                glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
+                                             (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
+                                             (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
                             glGetFloatv(GL_MODELVIEW_MATRIX, M);
-                            //if(!isnormal(M[12])||!isnormal(M[13])||!isnormal(M[14]))test=0;
-                            //if(!isnormal(scale))test=1;
                             skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
                             skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
                             skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
-                            //test=2;
                             glPopMatrix();
                         }
                     }
                     if (!playerdetail || skeleton.free == 3) {
                         for (j = 0; j < skeleton.muscles[i].numverticeslow; j++) {
-                            glMatrixMode(GL_MODELVIEW);                                                        // Select The Modelview Matrix
+                            XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
+                            glMatrixMode(GL_MODELVIEW);
                             glPushMatrix();
-                            if (skeleton.muscles[i].parent1->label == abdomen || skeleton.muscles[i].parent2->label == abdomen)
-                                glTranslatef((skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].x)*proportionbody.x,
-                                             (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].y)*proportionbody.y,
-                                             (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].z)*proportionbody.z);
-                            if (skeleton.muscles[i].parent1->label == lefthand || skeleton.muscles[i].parent1->label == righthand || skeleton.muscles[i].parent1->label == leftwrist || skeleton.muscles[i].parent1->label == rightwrist || skeleton.muscles[i].parent1->label == leftelbow || skeleton.muscles[i].parent1->label == rightelbow || skeleton.muscles[i].parent2->label == leftelbow || skeleton.muscles[i].parent2->label == rightelbow)
-                                glTranslatef((skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].x)*proportionarms.x,
-                                             (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].y)*proportionarms.y,
-                                             (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].z)*proportionarms.z);
-                            if (skeleton.muscles[i].parent1->label == leftfoot || skeleton.muscles[i].parent1->label == rightfoot || skeleton.muscles[i].parent1->label == leftankle || skeleton.muscles[i].parent1->label == rightankle || skeleton.muscles[i].parent1->label == leftknee || skeleton.muscles[i].parent1->label == rightknee || skeleton.muscles[i].parent2->label == leftknee || skeleton.muscles[i].parent2->label == rightknee)
-                                glTranslatef((skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].x)*proportionlegs.x,
-                                             (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].y)*proportionlegs.y,
-                                             (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].z)*proportionlegs.z);
-                            if (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)
-                                glTranslatef((skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].x)*proportionhead.x,
-                                             (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].y)*proportionhead.y,
-                                             (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].z)*proportionhead.z);
+                            if (p1 == abdomen || p2 == abdomen)
+                                glTranslatef(v0.x * proportionbody.x,
+                                             v0.y * proportionbody.y,
+                                             v0.z * proportionbody.z);
+                            if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
+                                glTranslatef(v0.x * proportionarms.x,
+                                             v0.y * proportionarms.y,
+                                             v0.z * proportionarms.z);
+                            if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
+                                glTranslatef(v0.x * proportionlegs.x,
+                                             v0.y * proportionlegs.y,
+                                             v0.z * proportionlegs.z);
+                            if (p1 == head || p2 == head)
+                                glTranslatef(v0.x * proportionhead.x,
+                                             v0.y * proportionhead.y,
+                                             v0.z * proportionhead.z);
 
                             glGetFloatv(GL_MODELVIEW_MATRIX, M);
                             skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
@@ -5669,11 +6180,13 @@ int Person::DrawSkeleton()
                 if (skeleton.clothes && skeleton.muscles[i].numverticesclothes > 0) {
                     mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
 
-                    glMatrixMode(GL_MODELVIEW);                                                        // Select The Modelview Matrix
+                    glMatrixMode(GL_MODELVIEW);
                     glPushMatrix();
                     glLoadIdentity();
-                    if (!skeleton.free)glRotatef(tilt2, 1, 0, 0);
-                    if (!skeleton.free)glRotatef(tilt, 0, 0, 1);
+                    if (!skeleton.free)
+                        glRotatef(tilt2, 1, 0, 0);
+                    if (!skeleton.free)
+                        glRotatef(tilt, 0, 0, 1);
                     glTranslatef(mid.x, mid.y, mid.z);
                     skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
                     glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
@@ -5685,24 +6198,25 @@ int Person::DrawSkeleton()
                     glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
 
                     for (j = 0; j < skeleton.muscles[i].numverticesclothes; j++) {
-                        glMatrixMode(GL_MODELVIEW);                                                    // Select The Modelview Matrix
+                        XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
+                        glMatrixMode(GL_MODELVIEW);
                         glPushMatrix();
-                        if (skeleton.muscles[i].parent1->label == abdomen || skeleton.muscles[i].parent2->label == abdomen)
-                            glTranslatef((skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x)*proportionbody.x,
-                                         (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y)*proportionbody.y,
-                                         (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z)*proportionbody.z);
-                        if (skeleton.muscles[i].parent1->label == lefthand || skeleton.muscles[i].parent1->label == righthand || skeleton.muscles[i].parent1->label == leftwrist || skeleton.muscles[i].parent1->label == rightwrist || skeleton.muscles[i].parent1->label == leftelbow || skeleton.muscles[i].parent1->label == rightelbow || skeleton.muscles[i].parent2->label == leftelbow || skeleton.muscles[i].parent2->label == rightelbow)
-                            glTranslatef((skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x)*proportionarms.x,
-                                         (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y)*proportionarms.y,
-                                         (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z)*proportionarms.z);
-                        if (skeleton.muscles[i].parent1->label == leftfoot || skeleton.muscles[i].parent1->label == rightfoot || skeleton.muscles[i].parent1->label == leftankle || skeleton.muscles[i].parent1->label == rightankle || skeleton.muscles[i].parent1->label == leftknee || skeleton.muscles[i].parent1->label == rightknee || skeleton.muscles[i].parent2->label == leftknee || skeleton.muscles[i].parent2->label == rightknee)
-                            glTranslatef((skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x)*proportionlegs.x,
-                                         (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y)*proportionlegs.y,
-                                         (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z)*proportionlegs.z);
-                        if (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)
-                            glTranslatef((skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x)*proportionhead.x,
-                                         (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y)*proportionhead.y,
-                                         (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z)*proportionhead.z);
+                        if (p1 == abdomen || p2 == abdomen)
+                            glTranslatef(v0.x * proportionbody.x,
+                                         v0.y * proportionbody.y,
+                                         v0.z * proportionbody.z);
+                        if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
+                            glTranslatef(v0.x * proportionarms.x,
+                                         v0.y * proportionarms.y,
+                                         v0.z * proportionarms.z);
+                        if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
+                            glTranslatef(v0.x * proportionlegs.x,
+                                         v0.y * proportionlegs.y,
+                                         v0.z * proportionlegs.z);
+                        if (p1 == head || p2 == head)
+                            glTranslatef(v0.x * proportionhead.x,
+                                         v0.y * proportionhead.y,
+                                         v0.z * proportionhead.z);
                         glGetFloatv(GL_MODELVIEW_MATRIX, M);
                         skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
                         skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
@@ -5715,12 +6229,17 @@ int Person::DrawSkeleton()
             }
             if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
                 normalsupdatedelay = 1;
-                if (playerdetail || skeleton.free == 3)skeleton.drawmodel.CalculateNormals(0);
-                if (!playerdetail || skeleton.free == 3)skeleton.drawmodellow.CalculateNormals(0);
-                if (skeleton.clothes)skeleton.drawmodelclothes.CalculateNormals(0);
+                if (playerdetail || skeleton.free == 3)
+                    skeleton.drawmodel.CalculateNormals(0);
+                if (!playerdetail || skeleton.free == 3)
+                    skeleton.drawmodellow.CalculateNormals(0);
+                if (skeleton.clothes)
+                    skeleton.drawmodelclothes.CalculateNormals(0);
             } else {
-                if (playerdetail || skeleton.free == 3)skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
-                if (!playerdetail || skeleton.free == 3)skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
+                if (playerdetail || skeleton.free == 3)
+                    skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
+                if (!playerdetail || skeleton.free == 3)
+                    skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
                 if (skeleton.clothes) {
                     skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
                 }
@@ -5728,18 +6247,23 @@ int Person::DrawSkeleton()
         }
         framemult = .01;
         updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
-        if (updatedelaychange > -realmultiplier * 30)updatedelaychange = -realmultiplier * 30;
-        if (updatedelaychange > -framemult * 4)updatedelaychange = -framemult * 4;
-        if (skeleton.free == 1)updatedelaychange *= 6;
-        if (id == 0)updatedelaychange *= 8;
+        if (updatedelaychange > -realmultiplier * 30)
+            updatedelaychange = -realmultiplier * 30;
+        if (updatedelaychange > -framemult * 4)
+            updatedelaychange = -framemult * 4;
+        if (skeleton.free == 1)
+            updatedelaychange *= 6;
+        if (id == 0)
+            updatedelaychange *= 8;
         updatedelay += updatedelaychange;
 
-        glMatrixMode(GL_MODELVIEW);                                                    // Select The Modelview Matrix
+        glMatrixMode(GL_MODELVIEW);
         glPushMatrix();
-        if (!skeleton.free)glTranslatef(coords.x, coords.y - .02, coords.z);
-        if (skeleton.free)glTranslatef(coords.x, coords.y - .02, coords.z);
-        if (!skeleton.free)glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
-        if (!skeleton.free)glRotatef(yaw, 0, 1, 0);
+        glTranslatef(coords.x, coords.y - .02, coords.z);
+        if (!skeleton.free) {
+            glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
+            glRotatef(yaw, 0, 1, 0);
+        }
         if (showpoints) {
             glPointSize(5);
             glColor4f(.4, 1, .4, 1);
@@ -5748,19 +6272,23 @@ int Person::DrawSkeleton()
             glBegin(GL_POINTS);
             if (playerdetail)
                 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
-                    glVertex3f(skeleton.drawmodel.vertex[i].x, skeleton.drawmodel.vertex[i].y, skeleton.drawmodel.vertex[i].z);
+                    XYZ &v0 = skeleton.drawmodel.vertex[i];
+                    glVertex3f(v0.x, v0.y, v0.z);
                 }
             glEnd();
             glBegin(GL_LINES);
 
             if (playerdetail)
                 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
-                    glVertex3f(skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]].x, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]].y, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]].z);
-                    glVertex3f(skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]].x, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]].y, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]].z);
-                    glVertex3f(skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]].x, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]].y, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]].z);
-                    glVertex3f(skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]].x, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]].y, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]].z);
-                    glVertex3f(skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]].x, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]].y, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]].z);
-                    glVertex3f(skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]].x, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]].y, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]].z);
+                    XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
+                    XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
+                    XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
+                    glVertex3f(v0.x, v0.y, v0.z);
+                    glVertex3f(v1.x, v1.y, v1.z);
+                    glVertex3f(v1.x, v1.y, v1.z);
+                    glVertex3f(v2.x, v2.y, v2.z);
+                    glVertex3f(v2.x, v2.y, v2.z);
+                    glVertex3f(v0.x, v0.y, v0.z);
                 }
 
             glEnd();
@@ -5769,13 +6297,15 @@ int Person::DrawSkeleton()
         terrainlight = terrain.getLighting(coords.x, coords.z);
         distance = distsq(&viewer, &coords);
         distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
-        if (distance > 1)distance = 1;
+        if (distance > 1)
+            distance = 1;
         if (distance > 0) {
             terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
-            if (terrainheight < 1)terrainheight = 1;
-            if (terrainheight > 1.7)terrainheight = 1.7;
+            if (terrainheight < 1)
+                terrainheight = 1;
+            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);
@@ -5788,7 +6318,6 @@ int Person::DrawSkeleton()
                 glEnable(GL_BLEND);
             }
             if (tutoriallevel && id != 0) {
-                //glDisable(GL_TEXTURE_2D);
                 glColor4f(.7, .7, .7, 0.6);
                 glDepthMask(0);
                 glEnable(GL_LIGHTING);
@@ -5805,13 +6334,17 @@ int Person::DrawSkeleton()
             }
             if (playerdetail) {
                 if (!showpoints) {
-                    if ((tutoriallevel && id != 0))skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
-                    else skeleton.drawmodel.draw();
+                    if ((tutoriallevel && id != 0))
+                        skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
+                    else
+                        skeleton.drawmodel.draw();
                 }
             }
             if (!playerdetail) {
-                if ((tutoriallevel && id != 0))skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
-                else skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
+                if ((tutoriallevel && id != 0))
+                    skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
+                else
+                    skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
             }
 
             if (!(animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed))
@@ -5834,13 +6367,17 @@ int Person::DrawSkeleton()
                     glTranslatef(smoketex * .6, 0, 0);
                     if (playerdetail) {
                         if (!showpoints) {
-                            if ((tutoriallevel && id != 0))skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
-                            else skeleton.drawmodel.draw();
+                            if ((tutoriallevel && id != 0))
+                                skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
+                            else
+                                skeleton.drawmodel.draw();
                         }
                     }
                     if (!playerdetail) {
-                        if ((tutoriallevel && id != 0))skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
-                        else skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
+                        if ((tutoriallevel && id != 0))
+                            skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
+                        else
+                            skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
                     }
                 }
 
@@ -5853,8 +6390,10 @@ int Person::DrawSkeleton()
             if (skeleton.clothes) {
                 glDepthMask(0);
                 glEnable(GL_BLEND);
-                if (!immediate)skeleton.drawmodelclothes.draw();
-                if (immediate)skeleton.drawmodelclothes.drawimmediate();
+                if (!immediate)
+                    skeleton.drawmodelclothes.draw();
+                if (immediate)
+                    skeleton.drawmodelclothes.drawimmediate();
                 glDepthMask(1);
             }
         }
@@ -5876,7 +6415,8 @@ int Person::DrawSkeleton()
                             }
                         }
                         weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
-                        if (creature == wolftype)weaponpoint = (skeleton.joints[skeleton.jointlabels[rightwrist]].position * .7 + skeleton.joints[skeleton.jointlabels[righthand]].position * .3);
+                        if (creature == wolftype)
+                            weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
                     }
                     if (weapons[i].getType() == staff) {
                         for (j = 0; j < skeleton.num_muscles; j++) {
@@ -5889,21 +6429,25 @@ int Person::DrawSkeleton()
                                 weaponrotatemuscle = j;
                             }
                         }
-                        //weaponpoint=skeleton.joints[skeleton.jointlabels[rightwrist]].position;
+                        //weaponpoint=jointPos(rightwrist);
                         weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
-                        //weaponpoint+=skeleton.specialforward[1]*.1+(skeleton.joints[skeleton.jointlabels[rightwrist]].position-skeleton.joints[skeleton.jointlabels[rightelbow]].position);
+                        //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
                         XYZ tempnormthing, vec1, vec2;
-                        vec1 = (skeleton.joints[skeleton.jointlabels[rightwrist]].position - skeleton.joints[skeleton.jointlabels[rightelbow]].position);
-                        vec2 = (skeleton.joints[skeleton.jointlabels[rightwrist]].position - skeleton.joints[skeleton.jointlabels[rightshoulder]].position);
+                        vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
+                        vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
                         CrossProduct(&vec1, &vec2, &tempnormthing);
                         Normalise(&tempnormthing);
-                        if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (skeleton.joints[skeleton.jointlabels[rightwrist]].position - skeleton.joints[skeleton.jointlabels[rightelbow]].position);
+                        if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
+                            weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
                     }
                 }
                 if (weaponactive != k && weaponstuck != k) {
-                    if (weapons[i].getType() == knife)weaponpoint = skeleton.joints[skeleton.jointlabels[abdomen]].position + (skeleton.joints[skeleton.jointlabels[righthip]].position - skeleton.joints[skeleton.jointlabels[lefthip]].position) * .1 + (skeleton.joints[skeleton.jointlabels[rightshoulder]].position - skeleton.joints[skeleton.jointlabels[leftshoulder]].position) * .35;
-                    if (weapons[i].getType() == sword)weaponpoint = skeleton.joints[skeleton.jointlabels[abdomen]].position + (skeleton.joints[skeleton.jointlabels[lefthip]].position - skeleton.joints[skeleton.jointlabels[righthip]].position) * .09 + (skeleton.joints[skeleton.jointlabels[leftshoulder]].position - skeleton.joints[skeleton.jointlabels[rightshoulder]].position) * .33;
-                    if (weapons[i].getType() == staff)weaponpoint = skeleton.joints[skeleton.jointlabels[abdomen]].position + (skeleton.joints[skeleton.jointlabels[lefthip]].position - skeleton.joints[skeleton.jointlabels[righthip]].position) * .09 + (skeleton.joints[skeleton.jointlabels[leftshoulder]].position - skeleton.joints[skeleton.jointlabels[rightshoulder]].position) * .33;
+                    if (weapons[i].getType() == knife)
+                        weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
+                    if (weapons[i].getType() == sword)
+                        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) {
                             weaponrotatemuscle = j;
@@ -5911,8 +6455,10 @@ int Person::DrawSkeleton()
                     }
                 }
                 if (weaponstuck == k) {
-                    if (weaponstuckwhere == 0)weaponpoint = skeleton.joints[skeleton.jointlabels[abdomen]].position * .5 + skeleton.joints[skeleton.jointlabels[neck]].position * .5 - skeleton.forward * .8;
-                    else weaponpoint = skeleton.joints[skeleton.jointlabels[abdomen]].position * .5 + skeleton.joints[skeleton.jointlabels[neck]].position * .5 + skeleton.forward * .8;
+                    if (weaponstuckwhere == 0)
+                        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) {
                             weaponrotatemuscle = j;
@@ -5944,10 +6490,10 @@ int Person::DrawSkeleton()
                             weapons[i].smallrotation2 = 50;
                         }
                         if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
-                            XYZ temppoint1, temppoint2, tempforward;
+                            XYZ temppoint1, temppoint2;
                             float distance;
 
-                            temppoint1 = skeleton.joints[skeleton.jointlabels[righthand]].position;
+                            temppoint1 = jointPos(righthand);
                             temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
                             distance = findDistance(&temppoint1, &temppoint2);
                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
@@ -5959,13 +6505,14 @@ int Person::DrawSkeleton()
                             weapons[i].rotation3 = 0;
                             weapons[i].smallrotation = -90;
                             weapons[i].smallrotation2 = 0;
-                            if (temppoint1.x > temppoint2.x)weapons[i].rotation1 = 360 - weapons[i].rotation1;
+                            if (temppoint1.x > temppoint2.x)
+                                weapons[i].rotation1 = 360 - weapons[i].rotation1;
                         }
                         if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
-                            XYZ temppoint1, temppoint2, tempforward;
+                            XYZ temppoint1, temppoint2;
                             float distance;
 
-                            temppoint1 = skeleton.joints[skeleton.jointlabels[righthand]].position;
+                            temppoint1 = jointPos(righthand);
                             temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
                             distance = findDistance(&temppoint1, &temppoint2);
                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
@@ -5977,7 +6524,8 @@ int Person::DrawSkeleton()
                             weapons[i].rotation3 = 0;
                             weapons[i].smallrotation = 90;
                             weapons[i].smallrotation2 = 0;
-                            if (temppoint1.x > temppoint2.x)weapons[i].rotation1 = 360 - weapons[i].rotation1;
+                            if (temppoint1.x > temppoint2.x)
+                                weapons[i].rotation1 = 360 - weapons[i].rotation1;
                         }
                         if (animTarget == knifethrowanim) {
                             weapons[i].smallrotation = 90;
@@ -6005,10 +6553,10 @@ int Person::DrawSkeleton()
                             weapons[i].rotation3 = 0;
                         }
                         if ((animTarget == swordgroundstabanim && animCurrent == swordgroundstabanim) || (animTarget == swordsneakattackanim && animCurrent == swordsneakattackanim) || (animTarget == swordslashparryanim && animCurrent == swordslashparryanim) || (animTarget == swordslashparriedanim && animCurrent == swordslashparriedanim) || (animTarget == swordslashreversalanim && animCurrent == swordslashreversalanim) || (animTarget == swordslashreversedanim && animCurrent == swordslashreversedanim) || (animTarget == knifeslashreversalanim && animCurrent == knifeslashreversalanim) || (animTarget == knifeslashreversedanim && animCurrent == knifeslashreversedanim) || (animTarget == swordslashanim && animCurrent == swordslashanim) || (animTarget == drawleftanim && animCurrent == drawleftanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
-                            XYZ temppoint1, temppoint2, tempforward;
+                            XYZ temppoint1, temppoint2;
                             float distance;
 
-                            temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //skeleton.joints[skeleton.jointlabels[righthand]].position;
+                            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);
                             distance = findDistance(&temppoint1, &temppoint2);
                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
@@ -6020,17 +6568,18 @@ int Person::DrawSkeleton()
                             weapons[i].rotation3 = 0;
                             weapons[i].smallrotation = 90;
                             weapons[i].smallrotation2 = 0;
-                            if (temppoint1.x > temppoint2.x)weapons[i].rotation1 = 360 - weapons[i].rotation1;
+                            if (temppoint1.x > temppoint2.x)
+                                weapons[i].rotation1 = 360 - weapons[i].rotation1;
                         }
                     }
                     if (weapons[i].getType() == staff) {
                         weapons[i].smallrotation = 100;
                         weapons[i].smallrotation2 = 0;
                         if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
-                            XYZ temppoint1, temppoint2, tempforward;
+                            XYZ temppoint1, temppoint2;
                             float distance;
 
-                            temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //skeleton.joints[skeleton.jointlabels[righthand]].position;
+                            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);
                             distance = findDistance(&temppoint1, &temppoint2);
                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
@@ -6042,7 +6591,8 @@ int Person::DrawSkeleton()
                             weapons[i].rotation3 = 0;
                             weapons[i].smallrotation = 90;
                             weapons[i].smallrotation2 = 0;
-                            if (temppoint1.x > temppoint2.x)weapons[i].rotation1 = 360 - weapons[i].rotation1;
+                            if (temppoint1.x > temppoint2.x)
+                                weapons[i].rotation1 = 360 - weapons[i].rotation1;
                         }
                     }
                 }
@@ -6072,16 +6622,21 @@ 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 || isFlip() || isWallJump())calcrot = 1;
-    if (animCurrent != animTarget)calcrot = 1;
-    //if(id==0)calcrot=1;
-    if (skeleton.free == 2)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())
+        calcrot = 1;
+    if (animCurrent != animTarget)
+        calcrot = 1;
+    if (skeleton.free == 2)
+        calcrot = 0;
 
     return 0;
 }
 
 
+/* FUNCTION?
+ */
 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
 {
     static int i, j;
@@ -6098,8 +6653,10 @@ int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate,
 
     oldp1 = *p1;
     *p1 = *p1 - *move;
-    if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)return -1;
-    if (*rotate)*p1 = DoRotation(*p1, 0, -*rotate, 0);
+    if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
+        return -1;
+    if (*rotate)
+        *p1 = DoRotation(*p1, 0, -*rotate, 0);
     for (i = 0; i < 4; i++) {
         for (j = 0; j < model->TriangleNum; j++) {
             if (model->facenormals[j].y <= slopethreshold) {
@@ -6107,16 +6664,20 @@ int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate,
                 distance = abs((model->facenormals[j].x * p1->x) + (model->facenormals[j].y * p1->y) + (model->facenormals[j].z * p1->z) - ((model->facenormals[j].x * model->vertex[model->Triangles[j].vertex[0]].x) + (model->facenormals[j].y * model->vertex[model->Triangles[j].vertex[0]].y) + (model->facenormals[j].z * model->vertex[model->Triangles[j].vertex[0]].z)));
                 if (distance < radius) {
                     point = *p1 - model->facenormals[j] * distance;
-                    if (PointInTriangle( &point, model->facenormals[j], &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]]))intersecting = 1;
-                    if (!intersecting)intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
-                                                         &model->vertex[model->Triangles[j].vertex[1]],
-                                                         p1, &radius);
-                    if (!intersecting)intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
-                                                         &model->vertex[model->Triangles[j].vertex[2]],
-                                                         p1, &radius);
-                    if (!intersecting)intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
-                                                         &model->vertex[model->Triangles[j].vertex[2]],
-                                                         p1, &radius);
+                    if (PointInTriangle( &point, model->facenormals[j], &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]]))
+                        intersecting = 1;
+                    if (!intersecting)
+                        intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
+                                                                &model->vertex[model->Triangles[j].vertex[1]],
+                                                                p1, &radius);
+                    if (!intersecting)
+                        intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
+                                                                &model->vertex[model->Triangles[j].vertex[2]],
+                                                                p1, &radius);
+                    if (!intersecting)
+                        intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
+                                                                &model->vertex[model->Triangles[j].vertex[2]],
+                                                                p1, &radius);
                     end = *p1 - point;
                     if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
                         start = *p1;
@@ -6125,7 +6686,8 @@ 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))RagDoll(0);
+                                if (isFlip() && (frameTarget < 5 || animation[animTarget].label[frameTarget] == 7 || animation[animTarget].label[frameTarget] == 4))
+                                    RagDoll(0);
 
                                 if (animTarget == jumpupanim) {
                                     jumppower = -4;
@@ -6141,15 +6703,13 @@ int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate,
                                 }
 
                                 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
-                                    if (isFlip())jumppower = -4;
+                                    if (isFlip())
+                                        jumppower = -4;
                                     animTarget = getLanding();
                                     emit_sound_at(landsound, coords, 128.);
 
                                     if (id == 0) {
-                                        envsound[numenvsounds] = coords;
-                                        envsoundvol[numenvsounds] = 16;
-                                        envsoundlife[numenvsounds] = .4;
-                                        numenvsounds++;
+                                        addEnvSound(coords);
                                     }
                                 }
                             }
@@ -6168,25 +6728,32 @@ int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate,
                 intersecting = 0;
                 start = *p1;
                 start.y -= radius / 4;
-                distance = abs((model->facenormals[j].x * start.x) + (model->facenormals[j].y * start.y) + (model->facenormals[j].z * start.z) - ((model->facenormals[j].x * model->vertex[model->Triangles[j].vertex[0]].x) + (model->facenormals[j].y * model->vertex[model->Triangles[j].vertex[0]].y) + (model->facenormals[j].z * model->vertex[model->Triangles[j].vertex[0]].z)));
+                XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
+                XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
+                XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
+                distance = abs((model->facenormals[j].x * start.x)
+                               + (model->facenormals[j].y * start.y)
+                               + (model->facenormals[j].z * start.z)
+                               - ((model->facenormals[j].x * v0.x)
+                                  + (model->facenormals[j].y * v0.y)
+                                  + (model->facenormals[j].z * v0.z)));
                 if (distance < radius * .5) {
                     point = start - model->facenormals[j] * distance;
-                    if (PointInTriangle( &point, model->facenormals[j], &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]]))intersecting = 1;
-                    if (!intersecting)intersecting = sphere_line_intersection(model->vertex[model->Triangles[j].vertex[0]].x, model->vertex[model->Triangles[j].vertex[0]].y, model->vertex[model->Triangles[j].vertex[0]].z,
-                                                         model->vertex[model->Triangles[j].vertex[1]].x, model->vertex[model->Triangles[j].vertex[1]].y, model->vertex[model->Triangles[j].vertex[1]].z,
-                                                         p1->x, p1->y, p1->z, radius / 2);
-                    if (!intersecting)intersecting = sphere_line_intersection(model->vertex[model->Triangles[j].vertex[1]].x, model->vertex[model->Triangles[j].vertex[1]].y, model->vertex[model->Triangles[j].vertex[1]].z,
-                                                         model->vertex[model->Triangles[j].vertex[2]].x, model->vertex[model->Triangles[j].vertex[2]].y, model->vertex[model->Triangles[j].vertex[2]].z,
-                                                         p1->x, p1->y, p1->z, radius / 2);
-                    if (!intersecting)intersecting = sphere_line_intersection(model->vertex[model->Triangles[j].vertex[0]].x, model->vertex[model->Triangles[j].vertex[0]].y, model->vertex[model->Triangles[j].vertex[0]].z,
-                                                         model->vertex[model->Triangles[j].vertex[2]].x, model->vertex[model->Triangles[j].vertex[2]].y, model->vertex[model->Triangles[j].vertex[2]].z,
-                                                         p1->x, p1->y, p1->z, radius / 2);
+                    if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
+                        intersecting = 1;
+                    if (!intersecting)
+                        intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
+                    if (!intersecting)
+                        intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
+                    if (!intersecting)
+                        intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
                     end = *p1 - point;
                     if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
                         if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
                             start = velocity;
                             velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
-                            if (findLengthfast(&start) < findLengthfast(&velocity))velocity = start;
+                            if (findLengthfast(&start) < findLengthfast(&velocity))
+                                velocity = start;
                         }
                         *p1 += model->facenormals[j] * (distance - radius * .5);
                     }
@@ -6199,9 +6766,84 @@ int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate,
             }
         }
     }
-    if (*rotate)*p = DoRotation(*p, 0, *rotate, 0);
+    if (*rotate)
+        *p = DoRotation(*p, 0, *rotate, 0);
     *p = *p + *move;
-    if (*rotate)*p1 = DoRotation(*p1, 0, *rotate, 0);
+    if (*rotate)
+        *p1 = DoRotation(*p1, 0, *rotate, 0);
     *p1 += *move;
     return firstintersecting;
 }
+
+void Person::takeWeapon(int weaponId)
+{
+    weaponactive = 0;
+    weapons[weaponId].owner = id;
+    if (num_weapons > 0) {
+        weaponids[num_weapons] = weaponids[0];
+    }
+    num_weapons++;
+    weaponids[0] = weaponId;
+}
+
+void Person::addClothes()
+{
+    if (numclothes > 0) {
+        for (int i = 0; i < numclothes; i++) {
+            addClothes(i);
+        }
+        DoMipmaps();
+    }
+}
+
+bool Person::addClothes(const int& clothesId)
+{
+    LOGFUNC;
+    const char* fileName = clothes[clothesId];
+
+    GLubyte* array = &skeleton.skinText[0];
+
+    //Load Image
+    ImageRec texture;
+    bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
+
+    float alphanum;
+    //Is it valid?
+    if (opened) {
+        float tintr = clothestintr[clothesId];
+        float tintg = clothestintg[clothesId];
+        float tintb = clothestintb[clothesId];
+
+        if (tintr > 1) tintr = 1;
+        if (tintg > 1) tintg = 1;
+        if (tintb > 1) tintb = 1;
+
+        if (tintr < 0) tintr = 0;
+        if (tintg < 0) tintg = 0;
+        if (tintb < 0) tintb = 0;
+
+        int bytesPerPixel = texture.bpp / 8;
+
+        int tempnum = 0;
+        alphanum = 255;
+        for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
+            if (bytesPerPixel == 3)
+                alphanum = 255;
+            else if ((i + 1) % 4 == 0)
+                alphanum = texture.data[i];
+            if ((i + 1) % 4 || bytesPerPixel == 3) {
+                if ((i % 4) == 0)
+                    texture.data[i] *= tintr;
+                if ((i % 4) == 1)
+                    texture.data[i] *= tintg;
+                if ((i % 4) == 2)
+                    texture.data[i] *= tintb;
+                array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
+                tempnum++;
+            }
+        }
+        return 1;
+    } else {
+        return 0;
+    }
+}