]> 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 64876000e106b9879a446549b3a038b7490dc8b4..3729c4f6ebc3c31895da0956a59698b398cb1413 100644 (file)
@@ -25,6 +25,8 @@ along with Lugaru.  If not, see <http://www.gnu.org/licenses/>.
 #include "Sounds.h"
 #include "Awards.h"
 #include "Game.h"
+#include "Dialog.h"
+#include "Utils/Folders.h"
 
 extern float multiplier;
 extern Terrain terrain;
@@ -53,20 +55,8 @@ extern bool decals;
 extern float fadestart;
 extern bool freeze;
 extern bool winfreeze;
-extern float flashamount, flashr, flashg, flashb;
-extern int flashdelay;
 extern bool showpoints;
 extern bool immediate;
-extern int test;
-extern bool tilt2weird;
-extern bool tiltweird;
-extern bool midweird;
-extern bool proportionweird;
-extern bool vertexweird[6];
-extern XYZ envsound[30];
-extern float envsoundvol[30];
-extern float envsoundlife[30];
-extern int numenvsounds;
 extern int tutoriallevel;
 extern float smoketex;
 extern int tutorialstage;
@@ -77,12 +67,354 @@ extern float damagedealt;
 extern int hostile;
 extern float hostiletime;
 
-extern int indialogue;
-
 extern bool gamestarted;
 
 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
 
+Person::Person() :
+    whichpatchx(0),
+    whichpatchz(0),
+    animCurrent(bounceidleanim),
+    animTarget(bounceidleanim),
+    frameCurrent(0),
+    frameTarget(1),
+    oldanimCurrent(0),
+    oldanimTarget(0),
+    oldframeCurrent(0),
+    oldframeTarget(0),
+    howactive(typeactive),
+    parriedrecently(0),
+    superruntoggle(false),
+    lastattack(0), lastattack2(0), lastattack3(0),
+    currentoffset(), targetoffset(), offset(),
+    target(0),
+    transspeed(0),
+
+    realoldcoords(),
+    oldcoords(),
+    coords(),
+    velocity(),
+
+    proportionhead(),
+    proportionlegs(),
+    proportionarms(),
+    proportionbody(),
+
+    unconscioustime(0),
+
+    immobile(false),
+
+    velspeed(0),
+    targetyaw(0),
+    targetrot(0),
+    rot(0),
+    oldrot(0),
+    lookyaw(0),
+    lookpitch(0),
+    yaw(0),
+    pitch(0),
+    lowyaw(0),
+    tilt(0),
+    targettilt(0),
+    tilt2(0),
+    targettilt2(0),
+    rabbitkickenabled(false),
+
+    bloodloss(0),
+    bleeddelay(0),
+    skiddelay(0),
+    skiddingdelay(0),
+    deathbleeding(0),
+    tempdeltav(0),
+
+    damagetolerance(200),
+    damage(0),
+    permanentdamage(0),
+    superpermanentdamage(0),
+    lastcollide(0),
+    dead(0),
+
+    jumppower(5),
+    onground(false),
+
+    wentforweapon(0),
+
+    calcrot(false),
+
+    facing(),
+
+    bleeding(0),
+    bleedx(0), bleedy(0),
+    direction(0),
+    texupdatedelay(0),
+
+    headyaw(0), headpitch(0),
+    targetheadyaw(0), targetheadpitch(0),
+
+    onterrain(false),
+    pause(false),
+
+    grabdelay(0),
+
+    victim(nullptr),
+    hasvictim(false),
+
+    updatedelay(0),
+    normalsupdatedelay(0),
+
+    jumpstart(false),
+    forwardkeydown(false),
+    forwardstogglekeydown(false),
+    rightkeydown(false),
+    leftkeydown(false),
+    backkeydown(false),
+    jumpkeydown(false),
+    jumptogglekeydown(false),
+    crouchkeydown(false),
+    crouchtogglekeydown(false),
+    drawkeydown(false),
+    drawtogglekeydown(false),
+    throwkeydown(false),
+    throwtogglekeydown(false),
+    attackkeydown(false),
+    feint(false),
+    lastfeint(false),
+    headless(false),
+
+    crouchkeydowntime(0),
+    jumpkeydowntime(0),
+    freefall(false),
+
+    turnspeed(0),
+
+    aitype(passivetype),
+    aiupdatedelay(0),
+    losupdatedelay(0),
+    ally(0),
+    collide(0),
+    collided(-10),
+    avoidcollided(0),
+    loaded(false),
+    whichdirection(false),
+    whichdirectiondelay(0),
+    avoidsomething(false),
+    avoidwhere(),
+    blooddimamount(0),
+
+    staggerdelay(0),
+    blinkdelay(0),
+    twitchdelay(0),
+    twitchdelay2(0),
+    twitchdelay3(0),
+    lefthandmorphness(0),
+    righthandmorphness(0),
+    headmorphness(0),
+    chestmorphness(0),
+    tailmorphness(0),
+    targetlefthandmorphness(0),
+    targetrighthandmorphness(0),
+    targetheadmorphness(1),
+    targetchestmorphness(0),
+    targettailmorphness(0),
+    lefthandmorphstart(0), lefthandmorphend(0),
+    righthandmorphstart(0), righthandmorphend(0),
+    headmorphstart(0), headmorphend(0),
+    chestmorphstart(0), chestmorphend(0),
+    tailmorphstart(0), tailmorphend(0),
+
+    weaponmissdelay(0),
+    highreversaldelay(0),
+    lowreversaldelay(0),
+
+    creature(rabbittype),
+
+    id(0),
+
+    skeleton(),
+
+    speed(0),
+    scale(-1),
+    power(0),
+    speedmult(0),
+
+    protectionhead(0),
+    protectionhigh(0),
+    protectionlow(0),
+    armorhead(0),
+    armorhigh(0),
+    armorlow(0),
+    metalhead(false),
+    metalhigh(false),
+    metallow(false),
+
+    numclothes(0),
+
+    landhard(false),
+    bled(false),
+    spurt(false),
+    onfire(false),
+    onfiredelay(0),
+    burnt(0),
+
+    flamedelay(0),
+
+    playerdetail(0),
+
+    num_weapons(0),
+    weaponactive(-1),
+    weaponstuck(-1),
+    weaponstuckwhere(0),
+
+    numwaypoints(0),
+    pausetime(0),
+
+    headtarget(),
+    interestdelay(0),
+
+    finalfinaltarget(),
+    finaltarget(),
+    finalpathfindpoint(0),
+    targetpathfindpoint(0),
+    lastpathfindpoint(0),
+    lastpathfindpoint2(0),
+    lastpathfindpoint3(0),
+    lastpathfindpoint4(0),
+
+    waypoint(0),
+
+    lastseen(),
+    lastseentime(0),
+    lastchecktime(0),
+    stunned(0),
+    surprised(0),
+    runninghowlong(0),
+    occluded(0),
+    lastoccluded(0),
+    laststanding(0),
+    escapednum(0),
+
+    speechdelay(0),
+    neckspurtdelay(0),
+    neckspurtparticledelay(0),
+    neckspurtamount(0),
+
+    whichskin(0),
+    rabbitkickragdoll(false),
+
+    tempanimation(),
+
+    jumpclimb(false)
+{
+}
+
+/* Read a person in tfile. Throws an error if it’s not valid */
+Person::Person(FILE *tfile, int mapvers, unsigned i) : Person()
+{
+    id = i;
+    funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
+    if (mapvers >= 5) {
+        funpackf(tfile, "Bi", &howactive);
+    } else {
+        howactive = typeactive;
+    }
+    if (mapvers >= 3) {
+        funpackf(tfile, "Bf", &scale);
+    } else {
+        scale = -1;
+    }
+    if (mapvers >= 11) {
+        funpackf(tfile, "Bb", &immobile);
+    } else {
+        immobile = 0;
+    }
+    if (mapvers >= 12) {
+        funpackf(tfile, "Bf", &yaw);
+    } else {
+        yaw = 0;
+    }
+    targetyaw = yaw;
+    if (num_weapons < 0 || num_weapons > 5) {
+        throw InvalidPersonException();
+    }
+    if (num_weapons > 0 && num_weapons < 5) {
+        for (int j = 0; j < num_weapons; j++) {
+            weaponids[j] = weapons.size();
+            int type;
+            funpackf(tfile, "Bi", &type);
+            weapons.push_back(Weapon(type, id));
+        }
+    }
+    funpackf(tfile, "Bi", &numwaypoints);
+    for (int j = 0; j < numwaypoints; j++) {
+        funpackf(tfile, "Bf", &waypoints[j].x);
+        funpackf(tfile, "Bf", &waypoints[j].y);
+        funpackf(tfile, "Bf", &waypoints[j].z);
+        if (mapvers >= 5) {
+            funpackf(tfile, "Bi", &waypointtype[j]);
+        } else {
+            waypointtype[j] = wpkeepwalking;
+        }
+    }
+
+    funpackf(tfile, "Bi", &waypoint);
+    if (waypoint > (numwaypoints - 1)) {
+        waypoint = 0;
+    }
+
+    funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
+    funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
+    funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
+    funpackf(tfile, "Bf Bf", &power, &speedmult);
+
+    float headprop, legprop, armprop, bodyprop;
+
+    if (mapvers >= 4) {
+        funpackf(tfile, "Bf Bf Bf Bf", &headprop, &bodyprop, &armprop, &legprop);
+    } else {
+        headprop = 1;
+        bodyprop = 1;
+        armprop = 1;
+        legprop = 1;
+    }
+
+    if (creature == wolftype) {
+        proportionhead = 1.1 * headprop;
+        proportionbody = 1.1 * bodyprop;
+        proportionarms = 1.1 * armprop;
+        proportionlegs = 1.1 * legprop;
+    } else if (creature == rabbittype) {
+        proportionhead = 1.2 * headprop;
+        proportionbody = 1.05 * bodyprop;
+        proportionarms = 1.00 * armprop;
+        proportionlegs = 1.1 * legprop;
+        proportionlegs.y = 1.05 * legprop;
+    }
+
+    funpackf(tfile, "Bi", &numclothes);
+    for (int k = 0; k < numclothes; k++) {
+        int templength;
+        funpackf(tfile, "Bi", &templength);
+        for (int l = 0; l < templength; l++)
+            funpackf(tfile, "Bb", &clothes[k][l]);
+        clothes[k][templength] = '\0';
+        funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
+    }
+
+    loaded = true;
+
+    if (scale < 0) {
+        if (creature == wolftype) {
+            scale = .23;
+            damagetolerance = 300;
+        } else {
+            scale = .2;
+        }
+    }
+
+    oldcoords = coords;
+    realoldcoords = coords;
+}
+
 /* EFFECT
  *
  * USES:
@@ -186,7 +518,7 @@ void Person::CatchFire()
  */
 int Person::getIdle()
 {
-    if (indialogue != -1 && howactive == typeactive && creature == rabbittype)
+    if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype))
         return talkidleanim;
     if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
         if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
@@ -394,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);
@@ -412,23 +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 (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) {
@@ -1210,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);
@@ -1221,14 +1537,11 @@ void Person::DoDamage(float howmuch)
                     whichsound = rabbitpainsound;
                 if (i == 1 && damage > damagetolerance)
                     whichsound = rabbitpain1sound;
-                envsound[numenvsounds] = coords;
-                envsoundvol[numenvsounds] = 16;
-                envsoundlife[numenvsounds] = .4;
-                numenvsounds++;
             }
 
             if (whichsound != -1) {
                 emit_sound_at(whichsound, coords);
+                addEnvSound(coords);
             }
         }
     speechdelay = .3;
@@ -1486,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
@@ -1713,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);
                             }
 
                         }
@@ -1756,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) {
@@ -1804,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;
@@ -2032,7 +2319,6 @@ void Person::DoAnimations()
                             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);
 
@@ -2068,7 +2354,6 @@ void Person::DoAnimations()
                             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);
                     }
@@ -2099,7 +2384,6 @@ void Person::DoAnimations()
                             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);
 
@@ -2135,7 +2419,6 @@ void Person::DoAnimations()
                             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);
 
@@ -2165,7 +2448,6 @@ void Person::DoAnimations()
                             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);
                     }
@@ -2756,7 +3038,6 @@ void Person::DoAnimations()
                         }
                         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);
@@ -2789,7 +3070,6 @@ void Person::DoAnimations()
                         }
                         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);
@@ -2825,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 (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 (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) {
@@ -2996,12 +3269,10 @@ void Person::DoAnimations()
                     relative = victim->coords - oldcoords;
                     relative.y = 0;
                     Normalise(&relative);
-                    //relative=DoRotation(relative,0,-90,0);
                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
                         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);
 
@@ -3113,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);
@@ -3422,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;
@@ -3477,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) {
@@ -4164,11 +4434,7 @@ void Person::DoStuff()
                 }
 
                 if (id == 0) {
-                    flashamount = .5;
-                    flashr = 1;
-                    flashg = 0;
-                    flashb = 0;
-                    flashdelay = 0;
+                    Game::flash(.5, 0);
                 }
             }
 
@@ -4998,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;
@@ -5061,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;
@@ -5553,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);
                 }
             }
         }
@@ -5579,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
@@ -5598,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
@@ -6049,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);
@@ -6453,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);
                                     }
                                 }
                             }
@@ -6533,24 +6786,34 @@ void Person::takeWeapon(int weaponId)
     weaponids[0] = weaponId;
 }
 
-bool Person::addClothes(const int& clothesId)
+void Person::addClothes()
 {
-    return addClothes(clothes[clothesId]);
+    if (numclothes > 0) {
+        for (int i = 0; i < numclothes; i++) {
+            addClothes(i);
+        }
+        DoMipmaps();
+    }
 }
 
-bool Person::addClothes(const char* fileName)
+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(fileName, 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;