]> 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 52b9b207b20984374edb08d0458b7996b85dab92..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,25 +67,352 @@ extern float damagedealt;
 extern int hostile;
 extern float hostiletime;
 
-extern int indialogue;
-
 extern bool gamestarted;
 
-Person player[maxplayers];
-
-/* convenience functions
- */
-Joint& Person::joint(int bodypart)
+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)
 {
-    return skeleton.joints[skeleton.jointlabels[bodypart]];
 }
-XYZ& Person::jointPos(int bodypart)
-{
-    return joint(bodypart).position;
-}
-XYZ& Person::jointVel(int bodypart)
+
+/* Read a person in tfile. Throws an error if it’s not valid */
+Person::Person(FILE *tfile, int mapvers, unsigned i) : Person()
 {
-    return joint(bodypart).velocity;
+    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
@@ -110,7 +425,7 @@ 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
@@ -160,7 +475,7 @@ void Person::CheckKick()
         victim->oldcoords = victim->coords;
         coords = victim->coords;
         victim->targetyaw = targetyaw;
-        victim->victim = this;
+        victim->victim = this->shared_from_this();
     }
 }
 
@@ -177,14 +492,13 @@ void Person::CatchFire()
     int howmany;
     for (int i = 0; i < 10; i++) {
         howmany = abs(Random() % (skeleton.num_joints));
-        if (!skeleton.free)
-            flatvelocity = velocity;
-        if (skeleton.free)
+        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;
+        } 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);
     }
 
@@ -204,10 +518,12 @@ void Person::CatchFire()
  */
 int Person::getIdle()
 {
-    if (indialogue != -1 && howactive == typeactive && creature == rabbittype)
+    if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype))
         return talkidleanim;
-    if (hasvictim && victim != this/*||(id==0&&attackkeydown)*/)
-        if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype && victim->aitype != searchtype && aitype != passivetype && aitype != searchtype && victim->id < numplayers)) {
+    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;
@@ -325,29 +641,21 @@ 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(jointVel(head), ((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, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
                     Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
-                }
-                if (!skeleton.free) {
+                } 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);
                 }
@@ -418,17 +726,12 @@ void Person::DoBloodBig(float howmuch, int which)
             // play pain sounds
             int whichsound = -1;
 
-            // FIXME: seems to be spawning sounds by manipulating attributes... MESSY!
             if (creature == wolftype) {
                 int i = abs(Random() % 2);
                 if (i == 0)
                     whichsound = snarlsound;
                 if (i == 1)
                     whichsound = snarl2sound;
-                envsound[numenvsounds] = coords;
-                envsoundvol[numenvsounds] = 16;
-                envsoundlife[numenvsounds] = .4;
-                numenvsounds++;
             }
             if (creature == rabbittype) {
                 int i = abs(Random() % 2);
@@ -436,24 +739,16 @@ void Person::DoBloodBig(float howmuch, int which)
                     whichsound = rabbitpainsound;
                 if (i == 1 && howmuch >= 2)
                     whichsound = rabbitpain1sound;
-                envsound[numenvsounds] = coords;
-                envsoundvol[numenvsounds] = 16;
-                envsoundlife[numenvsounds] = .4;
-                numenvsounds++;
-                //if(i==2)whichsound=rabbitpain2sound;
             }
 
-            if (whichsound != -1)
+            if (whichsound != -1) {
                 emit_sound_at(whichsound, coords);
+                addEnvSound(coords);
+            }
         }
 
     if (id == 0 && howmuch > 0) {
-        // FIXME: manipulating attributes
-        flashamount = .5;
-        flashr = 1;
-        flashg = 0;
-        flashb = 0;
-        flashdelay = 0;
+        Game::flash(.5, 0);
     }
 
     if (bloodtoggle && decals && tutoriallevel != 1) {
@@ -463,22 +758,15 @@ void Person::DoBloodBig(float howmuch, int which)
                 // 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(jointVel(head), ((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, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
                     Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
-                }
-                if (!skeleton.free) {
+                } 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);
                 }
@@ -641,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;
@@ -666,13 +953,6 @@ bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
             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);
@@ -702,31 +982,21 @@ 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(jointVel(head), ((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, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
                         Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
-                    }
-                    if (!skeleton.free) {
+                    } 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);
                     }
@@ -736,15 +1006,6 @@ bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
             // 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;
 
@@ -919,15 +1180,10 @@ 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];
@@ -936,8 +1192,8 @@ void Person::Reverse()
             }
 
             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;
             }
         }
 
@@ -949,15 +1205,10 @@ 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];
@@ -966,8 +1217,8 @@ void Person::Reverse()
             }
 
             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;
@@ -978,15 +1229,10 @@ 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];
@@ -995,8 +1241,8 @@ void Person::Reverse()
             }
 
             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;
@@ -1007,15 +1253,10 @@ 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];
@@ -1024,8 +1265,8 @@ void Person::Reverse()
             }
 
             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;
@@ -1033,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;
@@ -1043,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) {
@@ -1058,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) {
@@ -1068,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) {
@@ -1090,16 +1331,9 @@ 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];
@@ -1107,8 +1341,8 @@ void Person::Reverse()
                     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;
             }
         }
 
@@ -1133,16 +1367,9 @@ 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];
@@ -1150,8 +1377,8 @@ void Person::Reverse()
                     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;
             }
 
 
@@ -1265,14 +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)
+            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;
+            } 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;
@@ -1286,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);
         }
@@ -1308,10 +1530,6 @@ void Person::DoDamage(float howmuch)
                     whichsound = snarlsound;
                 if (i == 1)
                     whichsound = snarl2sound;
-                envsound[numenvsounds] = coords;
-                envsoundvol[numenvsounds] = 16;
-                envsoundlife[numenvsounds] = .4;
-                numenvsounds++;
             }
             if (creature == rabbittype) {
                 int i = abs(Random() % 2);
@@ -1319,21 +1537,14 @@ void Person::DoDamage(float howmuch)
                     whichsound = rabbitpainsound;
                 if (i == 1 && damage > damagetolerance)
                     whichsound = rabbitpain1sound;
-                envsound[numenvsounds] = coords;
-                envsoundvol[numenvsounds] = 16;
-                envsoundlife[numenvsounds] = .4;
-                numenvsounds++;
-                //if(i==2)whichsound=rabbitpain2sound;
             }
 
             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
@@ -1423,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);
             }
@@ -1470,19 +1680,18 @@ void Person::RagDoll(bool checkcollision)
         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;
             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;
         }
@@ -1503,7 +1712,7 @@ void Person::RagDoll(bool checkcollision)
 
         speed *= speedmult;
 
-        for (i = 0; i < skeleton.num_joints; i++) {
+        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
@@ -1556,7 +1765,7 @@ 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;
@@ -1564,15 +1773,8 @@ void Person::RagDoll(bool checkcollision)
         // 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 = jointVel(righthand) * scale * -.3;
+                weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
                 weapons[weaponids[0]].velocity.x += .01;
-                weapons[weaponids[0]].tipvelocity = jointVel(righthand) * 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];
@@ -1580,8 +1782,8 @@ void Person::RagDoll(bool checkcollision)
                         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;
                 }
             }
         }
@@ -1597,76 +1799,52 @@ void Person::RagDoll(bool checkcollision)
 
 /* EFFECT
  */
-void Person::FootLand(int which, float opacity)
+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(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
-            if (which == 1)
-                footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
-            //footpoint.y=coords.y;
+            footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
             if (distsq(&footpoint, &viewer))
                 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
-        } else if (environment == snowyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
+        } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
             footvel = velocity / 5;
             if (footvel.y < .8)
                 footvel.y = .8;
-            if (which == 0)
-                footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
-            if (which == 1)
-                footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
+            footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
             footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
             terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
-            if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
-                Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
-            if (opacity >= 1 || detail == 2)
-                if (detail == 2)
-                    if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
+            if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
+                if (environment == snowyenvironment) {
+                    Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
+                    if (detail == 2) {
                         terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
-        } else if (environment == grassyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
-            footvel = velocity / 5;
-            if (footvel.y < .8)
-                footvel.y = .8;
-            if (which == 0)
-                footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
-            if (which == 1)
-                footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
-            footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
-            terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
-            if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
-                Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
-        } else if (environment == desertenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
-            footvel = velocity / 5;
-            if (footvel.y < .8)
-                footvel.y = .8;
-            if (which == 0)
-                footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
-            if (which == 1)
-                footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
-            footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
-            terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
-            if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
-                Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
-            if (opacity >= 1 || detail == 2)
-                if (detail == 2)
-                    if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
+                    }
+                } else if (environment == grassyenvironment) {
+                    Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
+                } else if (environment == desertenvironment) {
+                    Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
+                    if (detail == 2) {
                         terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
-        } else if (isLanding() || animTarget == jumpupanim || isLandhard()) {
+                    }
+                }
+            }
+        } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
             footvel = velocity / 5;
             if (footvel.y < .8)
                 footvel.y = .8;
-            if (which == 0)
-                footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
-            if (which == 1)
-                footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
-            //footpoint.y=coords.y;
-            if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
+            footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
+            if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
                 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
+            }
         }
+    }
 }
 
 /* EFFECT
@@ -1698,7 +1876,6 @@ void Person::setAnimation(int animation)
 void Person::DoAnimations()
 {
     if (!skeleton.free) {
-        int i = 0;
         static float oldtarget;
 
         if (isIdle() && animCurrent != getIdle())
@@ -1773,7 +1950,6 @@ 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 (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
@@ -1826,12 +2002,12 @@ void Person::DoAnimations()
                             else
                                 whichsound = footstepsound2;
                             if (animation[animTarget].label[frameTarget] == 1)
-                                FootLand(0, 1);
+                                FootLand(leftfoot, 1);
                             if (animation[animTarget].label[frameTarget] == 2)
-                                FootLand(1, 1);
+                                FootLand(rightfoot, 1);
                             if (animation[animTarget].label[frameTarget] == 3 && isRun()) {
-                                FootLand(1, 1);
-                                FootLand(0, 1);
+                                FootLand(rightfoot, 1);
+                                FootLand(leftfoot, 1);
                             }
 
                         }
@@ -1850,12 +2026,12 @@ void Person::DoAnimations()
                     }
                     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)
+                            unsigned r = abs(Random() % 3);
+                            if (r == 0)
                                 whichsound = lowwhooshsound;
-                            if (i == 1)
+                            if (r == 1)
                                 whichsound = midwhooshsound;
-                            if (i == 2)
+                            if (r == 2)
                                 whichsound = highwhooshsound;
                         }
                         if (animation[animTarget].attack == neutral)
@@ -1869,13 +2045,11 @@ void Person::DoAnimations()
 
                     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) {
@@ -1892,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);
@@ -1920,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;
@@ -1931,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) {
@@ -1939,33 +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)
+                        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 == victim->id && victim->skeleton.free))
+                    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;
                                         }
                                     }
@@ -1976,10 +2141,8 @@ void Person::DoAnimations()
                                         emit_sound_at(knifedrawsound, coords, 128.);
                                     }
                                 }
-                                weaponactive = 0;
                                 if (weapons[i].owner != -1) {
-
-                                    victim = &player[weapons[i].owner];
+                                    victim = Person::players[weapons[i].owner];
                                     if (victim->num_weapons == 1)
                                         victim->num_weapons = 0;
                                     else
@@ -2003,7 +2166,7 @@ void Person::DoAnimations()
                                     footvel = 0;
                                     footpoint = weapons[i].position;
                                     if (victim->weaponstuck != -1) {
-                                        if (victim->weaponids[victim->weaponstuck] == i) {
+                                        if (victim->weaponids[victim->weaponstuck] == int(i)) {
                                             if (bloodtoggle)
                                                 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
                                             weapons[i].bloody = 2;
@@ -2014,7 +2177,7 @@ void Person::DoAnimations()
                                     if (victim->num_weapons > 0) {
                                         if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
                                             victim->weaponstuck = 0;
-                                        if (victim->weaponids[0] == i)
+                                        if (victim->weaponids[0] == int(i))
                                             victim->weaponids[0] = victim->weaponids[victim->num_weapons];
                                     }
 
@@ -2023,12 +2186,7 @@ void Person::DoAnimations()
                                     victim->jointVel(rightshoulder) += relative * 6;
                                     victim->jointVel(leftshoulder) += relative * 6;
                                 }
-                                weapons[i].owner = id;
-                                if (num_weapons > 0) {
-                                    weaponids[num_weapons] = weaponids[0];
-                                }
-                                num_weapons++;
-                                weaponids[0] = i;
+                                takeWeapon(i);
                             }
                         }
                 }
@@ -2074,7 +2232,7 @@ void Person::DoAnimations()
             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)
+                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;
@@ -2093,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;
@@ -2131,7 +2289,6 @@ void Person::DoAnimations()
             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) {
@@ -2158,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->jointVel(head) += relative * damagemult * 200;
-                        //FootLand(1,2);
                         victim->Puff(head);
                         victim->DoDamage(damagemult * 100 / victim->protectionhead);
 
@@ -2194,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->jointVel(head) += relative * damagemult * 100;
-                        //FootLand(1,2);
                         victim->Puff(head);
                         victim->DoDamage(damagemult * 50 / victim->protectionhead);
                     }
@@ -2225,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->jointVel(head) += relative * damagemult * 200;
-                        //FootLand(1,2);
                         victim->Puff(head);
                         victim->DoDamage(damagemult * 150 / victim->protectionhead);
 
@@ -2261,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->jointVel(head) += relative * damagemult * 200;
-                        //FootLand(1,2);
                         victim->Puff(head);
                         victim->DoDamage(damagemult * 150 / victim->protectionhead);
 
@@ -2291,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->jointVel(head) += relative * damagemult * 100;
-                        //FootLand(1,2);
                         victim->Puff(head);
                         victim->DoDamage(damagemult * 50 / victim->protectionhead);
                     }
@@ -2313,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;
@@ -2324,7 +2476,7 @@ 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;
@@ -2347,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);
@@ -2374,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;
@@ -2384,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)
@@ -2402,7 +2554,6 @@ void Person::DoAnimations()
                 }
 
                 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 5) {
-                    //if(id==0)camerashake+=.4;
 
                     if (hasvictim)
                         if (!victim->skeleton.free)
@@ -2471,7 +2622,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;
@@ -2561,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;
@@ -2608,7 +2759,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 * 30;
                         }
                         victim->jointVel(head) += relative * damagemult * 150;
@@ -2655,7 +2806,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 * 5;
                         }
                         victim->jointVel(abdomen) += relative * damagemult * 400;
@@ -2709,19 +2860,9 @@ void Person::DoAnimations()
                     if (weaponactive != -1) {
                         escapednum = 0;
                         XYZ aim;
-                        weapons[weaponids[0]].owner = -1;
                         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];
@@ -2765,8 +2906,7 @@ void Person::DoAnimations()
                             footvel = 0;
                             if (skeleton.free) {
                                 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
-                            }
-                            if (!skeleton.free) {
+                            } else {
                                 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
                             }
                             if (tutoriallevel != 1) {
@@ -2821,8 +2961,7 @@ void Person::DoAnimations()
                                 footvel = 0;
                                 if (skeleton.free) {
                                     footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
-                                }
-                                if (!skeleton.free) {
+                                } else {
                                     footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
                                 }
                                 if (bloodtoggle)
@@ -2856,16 +2995,9 @@ 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];
@@ -2873,8 +3005,8 @@ void Person::DoAnimations()
                                     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;
                             }
 
                         }
@@ -2901,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->jointVel(head) += relative * damagemult * 230;
                         victim->jointVel(neck) += relative * damagemult * 230;
-                        //FootLand(1,2);
                         victim->Puff(head);
                         if (tutoriallevel != 1) {
                             victim->DoDamage(damagemult * 120 / victim->protectionhigh);
@@ -2934,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->jointVel(head) += relative * damagemult * 220;
                         victim->jointVel(neck) += relative * damagemult * 220;
-                        //FootLand(1,2);
                         victim->Puff(head);
                         if (tutoriallevel != 1) {
                             victim->DoDamage(damagemult * 350 / victim->protectionhead);
@@ -2966,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;
@@ -2975,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->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->jointVel(abdomen)+=relative*damagemult*20;
                         }
                         victim->Puff(abdomen);
                         if (tutoriallevel != 1) {
@@ -3024,7 +3147,7 @@ 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->jointVel(head) += relative * damagemult * 200;
@@ -3043,7 +3166,7 @@ void Person::DoAnimations()
                         } else {
                             if (victim->damage >= victim->damagetolerance)
                                 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 * 10;
                             }
                             victim->jointVel(abdomen) += relative * damagemult * 200;
@@ -3067,7 +3190,9 @@ 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;
@@ -3082,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;
                             }
@@ -3097,11 +3222,11 @@ void Person::DoAnimations()
                         } else {
                             if (victim->damage >= victim->damagetolerance)
                                 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 * 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;
                             }
@@ -3144,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->jointVel(abdomen) += relative * damagemult * 200;
-                    //FootLand(1,2);
                     victim->Puff(abdomen);
                     victim->DoDamage(damagemult * 150 / victim->protectionhigh);
 
@@ -3158,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;
                         }
@@ -3190,12 +3306,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->jointVel(abdomen) += relative * damagemult * 200;
-                    //FootLand(1,2);
                     victim->Puff(head);
                     victim->DoDamage(damagemult * 70 / victim->protectionhigh);
                 }
@@ -3221,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->jointVel(abdomen) += relative * damagemult * 200;
-                    //FootLand(1,2);
                     victim->Puff(head);
                     victim->DoDamage(damagemult * 70 / victim->protectionhigh);
                 }
@@ -3238,9 +3350,8 @@ 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->jointVel(lefthand) *= .1;
@@ -3273,7 +3384,6 @@ void Person::DoAnimations()
                             weapons[weaponids[weaponactive]].blooddrip += 3;
                         }
                         if (weaponactive == -1 && creature == wolftype) {
-                            ;
                             emit_sound_at(clawslicesound, victim->coords, 128.);
                             victim->spurt = 1;
                             victim->DoBloodBig(2 / victim->armorhigh, 175);
@@ -3290,9 +3400,8 @@ 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->jointVel(lefthand) *= .1 - 1;
@@ -3324,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->jointVel(abdomen) += relative * damagemult * 200;
-                    //FootLand(1,2);
                     victim->Puff(abdomen);
                     victim->DoDamage(damagemult * 30 / victim->protectionhigh);
 
@@ -3345,10 +3453,9 @@ void Person::DoAnimations()
                     Normalise(&relative);
                     if (victim->id == 0)
                         relative /= 30;
-                    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->DoDamage(1000);
                     victim->damage = victim->damagetolerance;
                     victim->permanentdamage = victim->damagetolerance - 1;
                     bool doslice;
@@ -3382,14 +3489,6 @@ void Person::DoAnimations()
                         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(jointPos(neck),0,yaw,0)*scale+coords,bloodvel, 1,1,1, .05, 1);
-                            */
                             XYZ footvel, footpoint;
                             footvel = 0;
                             footpoint = weapons[weaponids[0]].tippoint;
@@ -3429,12 +3528,12 @@ 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;
                         }
                     }
@@ -3487,7 +3586,7 @@ 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) {
@@ -3549,14 +3648,13 @@ 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->jointVel(head) += relative * damagemult * 200;
@@ -3570,14 +3668,13 @@ 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->jointVel(head) += relative * damagemult * 200;
@@ -3595,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;
@@ -3650,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) {
@@ -3690,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;
@@ -3701,7 +3798,7 @@ 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;
@@ -3748,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;
@@ -3759,7 +3856,7 @@ 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;
@@ -4045,18 +4142,18 @@ 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;
@@ -4068,18 +4165,18 @@ void Person::DoAnimations()
                 }
 
                 //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;
@@ -4104,12 +4201,12 @@ void Person::DoAnimations()
             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);
@@ -4128,7 +4225,6 @@ void Person::DoAnimations()
             transspeed = 15;
         }
     }
-    //skeleton.DoConstraints();
 }
 
 /* EFFECT
@@ -4181,7 +4277,7 @@ void Person::DoStuff()
     flamedelay -= multiplier;
     parriedrecently -= multiplier;
     if (!victim) {
-        victim = this;
+        victim = this->shared_from_this();
         hasvictim = 0;
     }
 
@@ -4200,7 +4296,7 @@ void Person::DoStuff()
         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;
             }
         }
@@ -4219,8 +4315,6 @@ void Person::DoStuff()
 
     if (onfire) {
         burnt += multiplier;
-        /*if(aitype!=playercontrolled)*///deathbleeding=5;
-        /*if(aitype!=playercontrolled)*/
         deathbleeding = 1;
         if (burnt > .6)
             burnt = .6;
@@ -4245,28 +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)
+        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;
+        } 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)
+        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;
+        } 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);
     }
 
@@ -4274,7 +4366,7 @@ void Person::DoStuff()
         bleeding -= multiplier * .3;
         if (bloodtoggle == 2) {
             skeleton.drawmodel.textureptr.bind();
-            if (bleeding <= 0 && (detail != 2 || osx))
+            if ((bleeding <= 0) && (detail != 2))
                 DoMipmaps();
         }
     }
@@ -4286,21 +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);
-            }
-            if (skeleton.free)
                 bloodvel += DoRotation(jointVel(head), ((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, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
-            if (!skeleton.free)
+            } 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);
+            }
             neckspurtparticledelay = .05;
         }
         if (neckspurtdelay < 0) {
@@ -4318,32 +4405,23 @@ void Person::DoStuff()
             XYZ bloodvel;
             if (bloodtoggle) {
                 bloodvel = 0;
-                if (skeleton.free)
+                if (skeleton.free) {
                     bloodvel += DoRotation(jointVel(abdomen), ((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, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
-                if (!skeleton.free)
+                } 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 (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];
@@ -4351,16 +4429,12 @@ void Person::DoStuff()
                         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);
                 }
             }
 
@@ -4369,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;
                 }
@@ -4426,24 +4500,23 @@ void Person::DoStuff()
                 }
             }
         }
-        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;
+        } else {
+            bleedy -= 4 / realtexdetail;
+            if (detail == 2)
+                bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
+            else
+                bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
         }
     }
 
@@ -4538,14 +4611,13 @@ 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)
+                if (skeleton.free) {
                     footvel = skeleton.specialforward[0] * -1;
-                if (!skeleton.free)
-                    footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
-                if (skeleton.free)
                     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);
@@ -4761,15 +4833,8 @@ 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];
@@ -4777,8 +4842,8 @@ void Person::DoStuff()
                     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;
             }
         }
 
@@ -4792,16 +4857,13 @@ 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 (isIdle() || isCrouch()) {
         if (!dead)
             permanentdamage -= multiplier * 4;
-        //if(!dead&&deathbleeding<=0&&id==0)bloodloss-=multiplier*4;
     }
     if (damage < 0)
         damage = 0;
@@ -4819,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;
         }
     }
@@ -4827,15 +4889,8 @@ 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];
@@ -4843,8 +4898,8 @@ void Person::DoStuff()
                     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;
             }
         }
 
@@ -4911,9 +4966,8 @@ void Person::DoStuff()
         }
         average /= multiplier;
 
-        //velocity=jointVel(groin)*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;
@@ -5017,7 +5071,6 @@ void Person::DoStuff()
                 yaw = targetyaw;
 
                 frameTarget = 0;
-                //     frameTarget=2;
                 animTarget = flipanim;
                 crouchtogglekeydown = 1;
                 target = 0;
@@ -5027,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);
                 }
@@ -5122,7 +5172,7 @@ void Person::DoStuff()
                 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);
                 }
@@ -5214,10 +5264,7 @@ void Person::DoStuff()
                             emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
 
                             if (id == 0) {
-                                envsound[numenvsounds] = coords;
-                                envsoundvol[numenvsounds] = 4 * findLength(&velocity);
-                                envsoundlife[numenvsounds] = .4;
-                                numenvsounds++;
+                                addEnvSound(coords, 4 * findLength(&velocity));
                             }
 
                             int howmany;
@@ -5277,10 +5324,7 @@ void Person::DoStuff()
                             emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
 
                             if (id == 0) {
-                                envsound[numenvsounds] = coords;
-                                envsoundvol[numenvsounds] = 4 * findLength(&velocity);
-                                envsoundlife[numenvsounds] = .4;
-                                numenvsounds++;
+                                addEnvSound(coords, 4 * findLength(&velocity));
                             }
 
                             int howmany;
@@ -5328,7 +5372,7 @@ void Person::DoStuff()
     if (!skeleton.free) {
         bool play;
         play = 0;
-        if ((stunned > 0 || surprised > 0) && numplayers > 2 && aitype != passivetype)
+        if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
             play = 1;
         if (hasvictim)
             if (aitype != passivetype && victim->skeleton.free && !victim->dead)
@@ -5433,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;
@@ -5478,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);
             }
         }
@@ -5571,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);
@@ -5638,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);
@@ -5783,10 +5813,7 @@ void Person::DoStuff()
                 emit_sound_at(landsound, coords, 128.);
 
                 if (id == 0) {
-                    envsound[numenvsounds] = coords;
-                    envsoundvol[numenvsounds] = 16;
-                    envsoundlife[numenvsounds] = .4;
-                    numenvsounds++;
+                    addEnvSound(coords);
                 }
             }
         }
@@ -5809,8 +5836,8 @@ void Person::DoStuff()
             if (velspeed > 5 && (isLanding() || isLandhard())) {
                 skiddingdelay += multiplier;
                 if (skiddelay <= 0) {
-                    FootLand(0, .5);
-                    FootLand(1, .5);
+                    FootLand(leftfoot, .5);
+                    FootLand(rightfoot, .5);
                     skiddelay = .02;
                 }
             } else
@@ -5828,8 +5855,8 @@ void Person::DoStuff()
             if (velspeed > 5 && (isLanding() || isLandhard())) {
                 skiddingdelay += multiplier;
                 if (skiddelay <= 0) {
-                    FootLand(0, .5);
-                    FootLand(1, .5);
+                    FootLand(leftfoot, .5);
+                    FootLand(rightfoot, .5);
                     skiddelay = .02;
                 }
             } else
@@ -5887,7 +5914,7 @@ void Person::DoStuff()
  */
 void IKHelper(Person *p, float interp)
 {
-    XYZ point, newpoint, change, change2;
+    XYZ point, change, change2;
     float heightleft, heightright;
 
     // TODO: implement localToWorld and worldToLocal
@@ -6032,7 +6059,7 @@ 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;
@@ -6113,12 +6140,9 @@ int Person::DrawSkeleton()
                                              (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();
                         }
                     }
@@ -6235,14 +6259,11 @@ int Person::DrawSkeleton()
 
         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(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);
+        }
         if (showpoints) {
             glPointSize(5);
             glColor4f(.4, 1, .4, 1);
@@ -6285,7 +6306,6 @@ int Person::DrawSkeleton()
             if (terrainheight > 1.7)
                 terrainheight = 1.7;
 
-            //burnt=0;
             glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
             glDisable(GL_BLEND);
             glAlphaFunc(GL_GREATER, 0.0001);
@@ -6298,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);
@@ -6471,7 +6490,7 @@ 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 = jointPos(righthand);
@@ -6490,7 +6509,7 @@ int Person::DrawSkeleton()
                                 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 = jointPos(righthand);
@@ -6534,7 +6553,7 @@ 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); //jointPos(righthand);
@@ -6557,7 +6576,7 @@ int Person::DrawSkeleton()
                         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); //jointPos(righthand);
@@ -6605,11 +6624,10 @@ 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())
+    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(id==0)calcrot=1;
     if (skeleton.free == 2)
         calcrot = 0;
 
@@ -6691,10 +6709,7 @@ int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate,
                                     emit_sound_at(landsound, coords, 128.);
 
                                     if (id == 0) {
-                                        envsound[numenvsounds] = coords;
-                                        envsoundvol[numenvsounds] = 16;
-                                        envsoundlife[numenvsounds] = .4;
-                                        numenvsounds++;
+                                        addEnvSound(coords);
                                     }
                                 }
                             }
@@ -6760,3 +6775,75 @@ int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate,
     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;
+    }
+}