]> git.jsancho.org Git - lugaru.git/blobdiff - Source/Objects/Person.cpp
New non-atacking player
[lugaru.git] / Source / Objects / Person.cpp
index 817ee03734268e777c76543571c2faa279e51c0b..8022c0fc3323f023bc485bb3ff2eb20a7ae12ad9 100644 (file)
@@ -72,111 +72,7 @@ extern float envsoundlife[30];
 
 extern XYZ windvector;
 
-std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
-std::vector<PersonType> PersonType::types;
-
-PersonType::PersonType()
-{
-    animTalkIdle = tempanim;
-}
-
-bool PersonType::hasAnimTalkIdle()
-{
-    return (animTalkIdle != tempanim);
-}
-
-void PersonType::Load()
-{
-    types.resize(2);
-
-    /* Wolf */
-    types[wolftype].proportions[0] = 1.1;
-    types[wolftype].proportions[1] = 1.1;
-    types[wolftype].proportions[2] = 1.1;
-    types[wolftype].proportions[3] = 1.1;
-
-    types[wolftype].animRun = wolfrunanim;
-    types[wolftype].animRunning = wolfrunninganim;
-    types[wolftype].animCrouch = wolfcrouchanim;
-    types[wolftype].animStop = wolfstopanim;
-    types[wolftype].animLanding = wolflandanim;
-    types[wolftype].animLandingHard = wolflandhardanim;
-    types[wolftype].animFightIdle = wolfidle;
-    types[wolftype].animBounceIdle = wolfidle;
-
-    types[wolftype].soundsAttack[0] = barksound;
-    types[wolftype].soundsAttack[1] = bark2sound;
-    types[wolftype].soundsAttack[2] = bark3sound;
-    types[wolftype].soundsAttack[3] = barkgrowlsound;
-    types[wolftype].soundsTalk[0] = growlsound;
-    types[wolftype].soundsTalk[1] = growl2sound;
-
-    types[wolftype].figureFileName = "Skeleton/BasicFigureWolf";
-    types[wolftype].lowFigureFileName = "Skeleton/BasicFigureWolfLow";
-    types[wolftype].clothesFileName = "Skeleton/RabbitBelt";
-    types[wolftype].modelFileNames[0] = "Models/Wolf.solid";
-    types[wolftype].modelFileNames[1] = "Models/Wolf2.solid";
-    types[wolftype].modelFileNames[2] = "Models/Wolf3.solid";
-    types[wolftype].modelFileNames[3] = "Models/Wolf4.solid";
-    types[wolftype].modelFileNames[4] = "Models/Wolf5.solid";
-    types[wolftype].modelFileNames[5] = "Models/Wolf6.solid";
-    types[wolftype].modelFileNames[6] = "Models/Wolf7.solid";
-    types[wolftype].lowModelFileName = "Models/WolfLow.solid";
-    types[wolftype].modelClothesFileName = "Models/Belt.solid";
-
-    types[wolftype].skins.resize(3);
-    types[wolftype].skins[0] = "Textures/Wolf.jpg";
-    types[wolftype].skins[1] = "Textures/DarkWolf.jpg";
-    types[wolftype].skins[2] = "Textures/SnowWolf.jpg";
-
-    /* Rabbit */
-    types[rabbittype].proportions[0] = 1.2;
-    types[rabbittype].proportions[1] = 1.05;
-    types[rabbittype].proportions[2] = 1;
-    types[rabbittype].proportions[3] = 1.1;
-    types[rabbittype].proportions[3].y = 1.05;
-
-    types[rabbittype].animRun = runanim;
-    types[rabbittype].animRunning = rabbitrunninganim;
-    types[rabbittype].animCrouch = crouchanim;
-    types[rabbittype].animStop = stopanim;
-    types[rabbittype].animLanding = landanim;
-    types[rabbittype].animLandingHard = landhardanim;
-    types[rabbittype].animFightIdle = fightidleanim;
-    types[rabbittype].animBounceIdle = bounceidleanim;
-
-    types[rabbittype].soundsAttack[0] = rabbitattacksound;
-    types[rabbittype].soundsAttack[1] = rabbitattack2sound;
-    types[rabbittype].soundsAttack[2] = rabbitattack3sound;
-    types[rabbittype].soundsAttack[3] = rabbitattack4sound;
-    types[rabbittype].soundsTalk[0] = rabbitchitter;
-    types[rabbittype].soundsTalk[1] = rabbitchitter2;
-
-    types[rabbittype].figureFileName = "Skeleton/BasicFigure";
-    types[rabbittype].lowFigureFileName = "Skeleton/BasicFigureLow";
-    types[rabbittype].clothesFileName = "Skeleton/RabbitBelt";
-    types[rabbittype].modelFileNames[0] = "Models/Body.solid";
-    types[rabbittype].modelFileNames[1] = "Models/Body2.solid";
-    types[rabbittype].modelFileNames[2] = "Models/Body3.solid";
-    types[rabbittype].modelFileNames[3] = "Models/Body4.solid";
-    types[rabbittype].modelFileNames[4] = "Models/Body5.solid";
-    types[rabbittype].modelFileNames[5] = "Models/Body6.solid";
-    types[rabbittype].modelFileNames[6] = "Models/Body7.solid";
-    types[rabbittype].lowModelFileName = "Models/BodyLow.solid";
-    types[rabbittype].modelClothesFileName = "Models/Belt.solid";
-
-    types[rabbittype].skins.resize(10);
-    types[rabbittype].skins[0] = "Textures/Fur3.jpg";
-    types[rabbittype].skins[1] = "Textures/Fur.jpg";
-    types[rabbittype].skins[2] = "Textures/Fur2.jpg";
-    types[rabbittype].skins[3] = "Textures/Lynx.jpg";
-    types[rabbittype].skins[4] = "Textures/Otter.jpg";
-    types[rabbittype].skins[5] = "Textures/Opal.jpg";
-    types[rabbittype].skins[6] = "Textures/Sable.jpg";
-    types[rabbittype].skins[7] = "Textures/Chocolate.jpg";
-    types[rabbittype].skins[8] = "Textures/BW2.jpg";
-    types[rabbittype].skins[9] = "Textures/WB2.jpg";
-}
+std::vector<std::shared_ptr<Person>> Person::players;
 
 Person::Person()
     : whichpatchx(0)
@@ -234,30 +130,24 @@ Person::Person()
     , skiddingdelay(0)
     , deathbleeding(0)
     , tempdeltav(0)
-    ,
 
-    damagetolerance(200)
+    , damagetolerance(0)
     , damage(0)
     , permanentdamage(0)
     , superpermanentdamage(0)
     , lastcollide(0)
     , dead(0)
-    ,
 
-    jumppower(5)
+    jumppower(5)
     , onground(false)
-    ,
 
-    wentforweapon(0)
-    ,
+    , wentforweapon(0)
 
-    calcrot(false)
-    ,
+    , calcrot(false)
 
-    facing()
-    ,
+    , facing()
 
-    bleeding(0)
+    bleeding(0)
     , bleedx(0)
     , bleedy(0)
     , direction(0)
@@ -279,6 +169,7 @@ Person::Person()
 
     victim(nullptr)
     , hasvictim(false)
+    , isplayerfriend(false)
     ,
 
     updatedelay(0)
@@ -446,17 +337,15 @@ Person::Person()
     , neckspurtdelay(0)
     , neckspurtparticledelay(0)
     , neckspurtamount(0)
-    ,
 
-    whichskin(0)
+    whichskin(0)
     , rabbitkickragdoll(false)
-    ,
 
-    tempanimation()
-    ,
+    , tempanimation("Tempanim", lowheight, neutral)
 
-    jumpclimb(false)
+    jumpclimb(false)
 {
+    damagetolerance = PersonType::types[creature].defaultDamageTolerance;
     setProportions(1, 1, 1, 1);
 }
 
@@ -539,20 +428,26 @@ Person::Person(FILE* tfile, int mapvers, unsigned i)
 
     loaded = true;
 
+    damagetolerance = PersonType::types[creature].defaultDamageTolerance;
+
     if (scale < 0) {
-        if (creature == wolftype) {
-            scale = .23;
-            damagetolerance = 300;
-        } else {
-            scale = .2;
-        }
+        scale = PersonType::types[creature].defaultScale;
     }
 
     oldcoords = coords;
     realoldcoords = coords;
 }
 
-void Person::skeletonLoad(bool clothes)
+void Person::changeCreatureType(person_type type)
+{
+    creature = type;
+    whichskin = 0;
+    skeletonLoad();
+    scale = PersonType::types[creature].defaultScale;
+    damagetolerance = PersonType::types[creature].defaultDamageTolerance;
+}
+
+void Person::skeletonLoad()
 {
     skeleton.id = id;
     skeleton.Load(
@@ -568,7 +463,7 @@ void Person::skeletonLoad(bool clothes)
         PersonType::types[creature].modelFileNames[6],
         PersonType::types[creature].lowModelFileName,
         PersonType::types[creature].modelClothesFileName,
-        clothes);
+        PersonType::types[creature].clothes);
 
     skeleton.drawmodel.textureptr.load(PersonType::types[creature].skins[whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
 }
@@ -581,7 +476,12 @@ void Person::setProportions(float head, float body, float arms, float legs)
     proportions[3] = legs;
 }
 
-XYZ Person::getProportion(int part) const
+float Person::getProportion(int part) const
+{
+    return proportions[part];
+}
+
+XYZ Person::getProportionXYZ(int part) const
 {
     XYZ prop = PersonType::types[creature].proportions[part] * proportions[part];
     if (cellophane) {
@@ -602,7 +502,7 @@ void Person::CheckKick()
     }
 
     if (Animation::animations[victim->animTarget].height != lowheight) {
-        float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
+        float damagemult = PersonType::types[creature].power * power * power;
         XYZ relative = velocity;
         relative.y = 0;
         Normalise(&relative);
@@ -697,14 +597,14 @@ int Person::getIdle()
         if ((!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 ((isPlayerControlled() && (stunned <= 0) && !hasWeapon()) || pause) {
                 return PersonType::types[creature].animFightIdle;
             }
-            if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
+            if (isPlayerControlled() && (stunned <= 0) && hasWeapon()) {
                 if (weapons[weaponids[weaponactive]].getType() == knife) {
                     return knifefightidleanim;
                 }
-                if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1) {
+                if (weapons[weaponids[weaponactive]].getType() == sword && victim->hasWeapon()) {
                     return swordfightidlebothanim;
                 }
                 if (weapons[weaponids[weaponactive]].getType() == sword) {
@@ -714,13 +614,13 @@ int Person::getIdle()
                     return swordfightidleanim;
                 }
             }
-            if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause) {
+            if (!isPlayerControlled() && (stunned <= 0) && creature != wolftype) {
                 return fightsidestep;
             }
         }
     }
-    if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype) {
-        return hurtidleanim;
+    if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && PersonType::types[creature].hasAnimHurtIdle()) {
+        return PersonType::types[creature].animHurtIdle;
     }
     if (howactive == typesitting) {
         return sitanim;
@@ -759,7 +659,7 @@ int Person::getCrouch()
  */
 int Person::getRun()
 {
-    if (superruntoggle && (weaponactive == -1)) {
+    if (superruntoggle && (!hasWeapon())) {
         return PersonType::types[creature].animRunning;
     } else {
         return PersonType::types[creature].animRun;
@@ -887,7 +787,7 @@ void Person::DoBloodBig(float howmuch, int which)
     }
 
     if (!Tutorial::active || id == 0) {
-        if (aitype != playercontrolled && howmuch > 0) {
+        if (!isPlayerControlled() && howmuch > 0) {
             // play pain sounds
             int whichsound = -1;
 
@@ -1067,7 +967,7 @@ void Person::DoBloodBig(float howmuch, int which)
     deathbleeding += bleeding;
     bloodloss += bleeding * 3;
 
-    if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
+    if (!Tutorial::active && !isPlayerControlled() && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
         if (abs(Random() % 2) == 0) {
             aitype = gethelptype;
             lastseentime = 12;
@@ -1276,7 +1176,7 @@ bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
     deathbleeding += bleeding;
     bloodloss += bleeding * 3;
 
-    if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
+    if (!Tutorial::active && !isPlayerControlled() && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
         if (abs(Random() % 2) == 0) {
             aitype = gethelptype;
             lastseentime = 12;
@@ -1296,7 +1196,7 @@ bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
  */
 void Person::Reverse()
 {
-    if (!((victim->aitype == playercontrolled || hostiletime > 1 || staggerdelay <= 0) && victim->animTarget != jumpupanim && victim->animTarget != jumpdownanim && (!Tutorial::active || cananger) && hostile)) {
+    if (!((victim->isPlayerControlled() || hostiletime > 1 || staggerdelay <= 0) && victim->animTarget != jumpupanim && victim->animTarget != jumpdownanim && (!Tutorial::active || cananger) && hostile)) {
         return;
     }
 
@@ -1329,7 +1229,7 @@ void Person::Reverse()
         victim->animTarget = upunchreversalanim;
     }
     if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
-        if (victim->weaponactive != -1) {
+        if (victim->hasWeapon()) {
             victim->throwtogglekeydown = 1;
             XYZ tempVelocity = victim->velocity * .2;
             if (tempVelocity.x == 0) {
@@ -1356,7 +1256,7 @@ void Person::Reverse()
         victim->animTarget = staffhitreversalanim;
     }
     if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
-        if (victim->weaponactive != -1) {
+        if (victim->hasWeapon()) {
             victim->throwtogglekeydown = 1;
             XYZ tempVelocity = victim->velocity * .2;
             if (tempVelocity.x == 0) {
@@ -1382,7 +1282,7 @@ void Person::Reverse()
         victim->animTarget = staffspinhitreversalanim;
     }
     if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
-        if (victim->weaponactive != -1) {
+        if (victim->hasWeapon()) {
             victim->throwtogglekeydown = 1;
             XYZ tempVelocity = victim->velocity * .2;
             if (tempVelocity.x == 0) {
@@ -1408,7 +1308,7 @@ void Person::Reverse()
         victim->animTarget = swordslashreversalanim;
     }
     if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
-        if (victim->weaponactive != -1) {
+        if (victim->hasWeapon()) {
             victim->throwtogglekeydown = 1;
             XYZ tempVelocity = victim->velocity * .2;
             if (tempVelocity.x == 0) {
@@ -1461,7 +1361,7 @@ void Person::Reverse()
         victim->victim = this->shared_from_this();
         victim->targetyaw = targetyaw + 180;
     }
-    if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
+    if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->hasWeapon()) {
         animTarget = swordslashparriedanim;
         parriedrecently = .4;
         victim->parriedrecently = 0;
@@ -1472,7 +1372,7 @@ void Person::Reverse()
         victim->targetyaw = targetyaw + 180;
 
         if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
-            if (victim->weaponactive != -1) {
+            if (victim->hasWeapon()) {
                 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
                     if (weapons[victim->weaponids[0]].getType() == staff) {
                         weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
@@ -1509,7 +1409,7 @@ void Person::Reverse()
         }
 
         if (abs(Random() % 20) == 0) {
-            if (weaponactive != -1) {
+            if (hasWeapon()) {
                 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
                     if (weapons[victim->weaponids[0]].getType() == staff) {
                         weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
@@ -1594,7 +1494,7 @@ void Person::Reverse()
     velocity = 0;
     victim->velocity = 0;
 
-    if (aitype != playercontrolled) {
+    if (!isPlayerControlled()) {
         feint = 0;
         if (escapednum < 2) {
             int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
@@ -1654,7 +1554,7 @@ void Person::DoDamage(float howmuch)
     if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile)) {
         aitype = attacktypecutoff;
     }
-    if (!Tutorial::active && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
+    if (!Tutorial::active && !isPlayerControlled() && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
         if (abs(Random() % 2) == 0) {
             aitype = gethelptype;
             lastseentime = 12;
@@ -1697,7 +1597,7 @@ void Person::DoDamage(float howmuch)
 
     // play sounds
     if (!Tutorial::active || id == 0) {
-        if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
+        if (speechdelay <= 0 && !dead && !isPlayerControlled()) {
             int whichsound = -1;
 
             if (creature == wolftype) {
@@ -1990,7 +1890,7 @@ void Person::RagDoll(bool checkcollision)
 
         // drop weapon
         if (Random() % 2 == 0) {
-            if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
+            if (hasWeapon() && animTarget != rabbitkickanim && num_weapons > 0) {
                 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
                 weapons[weaponids[0]].velocity.x += .01;
                 num_weapons--;
@@ -2148,11 +2048,11 @@ void Person::DoAnimations()
         }
         if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
             crouchtogglekeydown = 0;
-            if (aitype == playercontrolled) {
+            if (isPlayerControlled()) {
                 feint = 0;
             }
         } else {
-            if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain)) {
+            if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && isPlayerControlled() && (escapednum < 2 || reversaltrain)) {
                 feint = 1;
             }
             if (!isFlip()) {
@@ -2191,8 +2091,7 @@ void Person::DoAnimations()
                     if (victim->aitype == gethelptype) {
                         victim->DoDamage(victim->damagetolerance - victim->damage);
                     }
-                    //victim->DoDamage(30);
-                    if (creature == wolftype) {
+                    if (PersonType::types[creature].hasClaws) {
                         DoBloodBig(0, 255);
                         emit_sound_at(clawslicesound, victim->coords);
                         victim->spurt = 1;
@@ -2203,20 +2102,15 @@ void Person::DoAnimations()
                 }
             }
 
-            if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
+            if (!drawtogglekeydown && drawkeydown && (!hasWeapon() || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
                 if (weapons[weaponids[0]].getType() == knife) {
-                    if (weaponactive == -1) {
+                    if (!hasWeapon()) {
                         weaponactive = 0;
+                        emit_sound_at(knifedrawsound, coords, 128);
                     } else if (weaponactive == 0) {
                         weaponactive = -1;
-                    }
-
-                    if (weaponactive == -1) {
                         emit_sound_at(knifesheathesound, coords);
                     }
-                    if (weaponactive != -1) {
-                        emit_sound_at(knifedrawsound, coords, 128);
-                    }
                 }
                 drawtogglekeydown = 1;
             }
@@ -2257,7 +2151,7 @@ void Person::DoAnimations()
                             whichsound = footstepsound4;
                         }
                     }
-                    if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
+                    if (targetFrame().label == 4 && (!hasWeapon() || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
                         if (Animation::animations[animTarget].attack != neutral) {
                             unsigned r = abs(Random() % 3);
                             if (r == 0) {
@@ -2307,7 +2201,7 @@ void Person::DoAnimations()
                     if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
                         if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
                             int whichsound = -1;
-                            if (targetFrame().label == 4 && aitype != playercontrolled) {
+                            if (targetFrame().label == 4 && !isPlayerControlled()) {
                                 if (Animation::animations[animTarget].attack != neutral) {
                                     unsigned r = abs(Random() % 4);
                                     whichsound = PersonType::types[creature].soundsAttack[r];
@@ -2334,10 +2228,10 @@ void Person::DoAnimations()
             animCurrent = animTarget;
             frameTarget++;
 
-            if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+            if (animCurrent == removeknifeanim && currentFrame().label == 5) {
                 for (unsigned i = 0; i < weapons.size(); i++) {
                     if (weapons[i].owner == -1) {
-                        if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
+                        if (distsqflat(&coords, &weapons[i].position) < 4 && !hasWeapon()) {
                             if (distsq(&coords, &weapons[i].position) >= 1) {
                                 if (weapons[i].getType() != staff) {
                                     emit_sound_at(knifedrawsound, coords, 128.);
@@ -2350,7 +2244,7 @@ void Person::DoAnimations()
                 }
             }
 
-            if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+            if (animCurrent == crouchremoveknifeanim && currentFrame().label == 5) {
                 for (unsigned i = 0; i < weapons.size(); i++) {
                     bool willwork = true;
                     if (weapons[i].owner != -1) {
@@ -2363,7 +2257,7 @@ void Person::DoAnimations()
                         }
                     }
                     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 (willwork && distsqflat(&coords, &weapons[i].position) < 3 && !hasWeapon()) {
                             if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
                                 bool fleshstuck = false;
                                 if (weapons[i].owner != -1) {
@@ -2436,9 +2330,10 @@ void Person::DoAnimations()
                 }
             }
 
-            if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
-                if (weaponactive == -1) {
+            if (animCurrent == drawleftanim && currentFrame().label == 5) {
+                if (!hasWeapon()) {
                     weaponactive = 0;
+                    emit_sound_at(knifedrawsound, coords, 128.);
                 } else if (weaponactive == 0) {
                     weaponactive = -1;
                     if (num_weapons == 2) {
@@ -2447,13 +2342,8 @@ void Person::DoAnimations()
                         weaponids[0] = weaponids[1];
                         weaponids[1] = buffer;
                     }
-                }
-                if (weaponactive == -1) {
                     emit_sound_at(knifesheathesound, coords, 128.);
                 }
-                if (weaponactive != -1) {
-                    emit_sound_at(knifedrawsound, coords, 128.);
-                }
             }
 
             if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
@@ -2536,31 +2426,28 @@ void Person::DoAnimations()
             }
 
             //Move impacts
-            float damagemult = 1 * power;
-            if (creature == wolftype) {
-                damagemult = 2.5 * power;
-            }
+            float damagemult = PersonType::types[creature].power * power;
             if (hasvictim) {
                 damagemult /= victim->damagetolerance / 200;
             }
             if ((Animation::animations[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
-                if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                if (animCurrent == spinkickanim && currentFrame().label == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
                         escapednum = 0;
                         if (id == 0) {
                             camerashake += .4;
                         }
-                        if (Random() % 2 || creature == wolftype) {
+                        if (Random() % 2 || PersonType::types[creature].hasClaws) {
                             victim->spurt = 1;
                             DoBlood(.2, 250);
-                            if (creature == wolftype) {
+                            if (PersonType::types[creature].hasClaws) {
                                 DoBloodBig(0, 250);
                             }
                         }
                         if (!Tutorial::active) {
                             emit_sound_at(heavyimpactsound, victim->coords, 128.);
                         }
-                        if (creature == wolftype) {
+                        if (PersonType::types[creature].hasClaws) {
                             emit_sound_at(clawslicesound, victim->coords, 128.);
                             victim->spurt = 1;
                             victim->DoBloodBig(2 / victim->armorhead, 175);
@@ -2582,20 +2469,20 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                if (animCurrent == wolfslapanim && currentFrame().label == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
                         escapednum = 0;
                         if (id == 0) {
                             camerashake += .4;
                         }
-                        if (Random() % 2 || creature == wolftype) {
+                        if (Random() % 2 || PersonType::types[creature].hasClaws) {
                             victim->spurt = 1;
-                            if (creature == wolftype) {
+                            if (PersonType::types[creature].hasClaws) {
                                 DoBloodBig(0, 235);
                             }
                         }
                         emit_sound_at(whooshhitsound, victim->coords);
-                        if (creature == wolftype) {
+                        if (PersonType::types[creature].hasClaws) {
                             emit_sound_at(clawslicesound, victim->coords, 128.);
                             victim->spurt = 1;
                             victim->DoBloodBig(2, 175);
@@ -2617,7 +2504,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                if (animCurrent == walljumprightkickanim && currentFrame().label == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
                         escapednum = 0;
                         if (id == 0) {
@@ -2628,7 +2515,7 @@ void Person::DoAnimations()
                         if (!Tutorial::active) {
                             emit_sound_at(heavyimpactsound, victim->coords, 160.);
                         }
-                        if (creature == wolftype) {
+                        if (PersonType::types[creature].hasClaws) {
                             emit_sound_at(clawslicesound, victim->coords, 128.);
                             victim->spurt = 1;
                             victim->DoBloodBig(2 / victim->armorhead, 175);
@@ -2654,7 +2541,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                if (animCurrent == walljumpleftkickanim && currentFrame().label == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
                         escapednum = 0;
                         if (id == 0) {
@@ -2665,7 +2552,7 @@ void Person::DoAnimations()
                         if (!Tutorial::active) {
                             emit_sound_at(heavyimpactsound, victim->coords, 160.);
                         }
-                        if (creature == wolftype) {
+                        if (PersonType::types[creature].hasClaws) {
                             emit_sound_at(clawslicesound, victim->coords, 128.);
                             victim->spurt = 1;
                             victim->DoBloodBig(2 / victim->armorhead, 175);
@@ -2691,7 +2578,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                if (animCurrent == blockhighleftstrikeanim && currentFrame().label == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
                         escapednum = 0;
                         if (id == 0) {
@@ -2716,7 +2603,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
+                if (animCurrent == killanim && currentFrame().label == 8) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
                         escapednum = 0;
                         if (id == 0) {
@@ -2751,7 +2638,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                if (animCurrent == killanim && currentFrame().label == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
                         escapednum = 0;
                         if (id == 0) {
@@ -2777,7 +2664,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
+                if (animCurrent == dropkickanim && currentFrame().label == 7) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
                         escapednum = 0;
                         if (id == 0) {
@@ -2819,7 +2706,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                if ((animCurrent == crouchstabanim || animCurrent == swordgroundstabanim) && currentFrame().label == 5) {
 
                     if (hasvictim) {
                         if (!victim->skeleton.free) {
@@ -2916,7 +2803,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
+                if ((animCurrent == crouchstabanim || animCurrent == swordgroundstabanim) && currentFrame().label == 6) {
                     if (!hasvictim) {
                         emit_sound_at(knifedrawsound, coords, 128);
                     }
@@ -3020,7 +2907,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                if (animCurrent == upunchanim && currentFrame().label == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
                         escapednum = 0;
                         if (id == 0) {
@@ -3058,7 +2945,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                if (animCurrent == winduppunchanim && currentFrame().label == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
                         escapednum = 0;
                         if (id == 0) {
@@ -3105,7 +2992,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                if (animCurrent == blockhighleftanim && currentFrame().label == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
                         if (victim->id == 0) {
                             camerashake += .4;
@@ -3116,13 +3003,13 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                if (animCurrent == swordslashparryanim && currentFrame().label == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
                         if (victim->id == 0) {
                             camerashake += .4;
                         }
 
-                        if (weaponactive != -1) {
+                        if (hasWeapon()) {
                             if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
                                 if (weapons[victim->weaponids[0]].getType() == staff) {
                                     weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
@@ -3141,8 +3028,8 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
-                    if (weaponactive != -1) {
+                if (animCurrent == knifethrowanim && currentFrame().label == 5) {
+                    if (hasWeapon()) {
                         escapednum = 0;
                         XYZ aim;
                         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);
@@ -3156,9 +3043,9 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                if (animCurrent == knifeslashstartanim && currentFrame().label == 5) {
                     if (hasvictim) {
-                        if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 && /*Animation::animations[victim->animTarget].height!=lowheight&&*/ victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
+                        if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 && victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
                             escapednum = 0;
                             if (!Tutorial::active) {
                                 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
@@ -3169,7 +3056,7 @@ void Person::DoAnimations()
                                 emit_sound_at(knifeslicesound, victim->coords);
                             }
                             //victim->jointVel(abdomen)+=relative*damagemult*200;
-                            if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
+                            if (Animation::animations[victim->animTarget].attack && (!victim->isPlayerControlled() || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
                                 if (victim->id != 0 || difficulty == 2) {
                                     victim->frameTarget = 0;
                                     victim->animTarget = staggerbackhardanim;
@@ -3179,7 +3066,7 @@ void Person::DoAnimations()
                             }
                             victim->lowreversaldelay = 0;
                             victim->highreversaldelay = 0;
-                            if (aitype != playercontrolled) {
+                            if (!isPlayerControlled()) {
                                 weaponmissdelay = .6;
                             }
 
@@ -3213,9 +3100,9 @@ void Person::DoAnimations()
                         }
                     }
                 }
-                if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
+                if (animCurrent == swordslashanim && currentFrame().label == 5 && victim->animTarget != rollanim) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
-                        if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
+                        if (!victim->hasWeapon() || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
                             award_bonus(id, Slashbonus);
                             escapednum = 0;
                             if (!Tutorial::active) {
@@ -3258,7 +3145,7 @@ void Person::DoAnimations()
                                 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
                             }
                         } else {
-                            if (victim->weaponactive != -1) {
+                            if (victim->hasWeapon()) {
                                 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
                                     if (weapons[victim->weaponids[0]].getType() == staff) {
                                         weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
@@ -3298,7 +3185,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
+                if (animCurrent == staffhitanim && currentFrame().label == 5 && victim->animTarget != rollanim) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
                         if (!Tutorial::active) {
                             weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
@@ -3306,7 +3193,7 @@ void Person::DoAnimations()
                             if (id == 0) {
                                 camerashake += .4;
                             }
-                            if (Random() % 2 || creature == wolftype) {
+                            if (Random() % 2 || PersonType::types[creature].hasClaws) {
                                 victim->spurt = 1;
                             }
                             emit_sound_at(staffheadsound, victim->coords);
@@ -3333,7 +3220,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
+                if (animCurrent == staffspinhitanim && currentFrame().label == 5 && victim->animTarget != rollanim) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
                         if (!Tutorial::active) {
                             weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
@@ -3341,7 +3228,7 @@ void Person::DoAnimations()
                             if (id == 0) {
                                 camerashake += .4;
                             }
-                            if (Random() % 2 || creature == wolftype) {
+                            if (Random() % 2 || PersonType::types[creature].hasClaws) {
                                 victim->spurt = 1;
                             }
                             emit_sound_at(staffheadsound, victim->coords);
@@ -3366,7 +3253,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                if (animCurrent == staffgroundsmashanim && currentFrame().label == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
                         escapednum = 0;
                         if (!Tutorial::active) {
@@ -3376,7 +3263,7 @@ void Person::DoAnimations()
                             if (id == 0) {
                                 camerashake += .4;
                             }
-                            if (Random() % 2 || creature == wolftype) {
+                            if (Random() % 2 || PersonType::types[creature].hasClaws) {
                                 victim->spurt = 1;
                             }
                             emit_sound_at(staffbodysound, victim->coords);
@@ -3418,7 +3305,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                if (animCurrent == lowkickanim && currentFrame().label == 5) {
                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
                         escapednum = 0;
                         if (id == 0) {
@@ -3449,7 +3336,7 @@ void Person::DoAnimations()
                             if (victim->howactive == typesleeping) {
                                 victim->DoDamage(damagemult * 150 / victim->protectionhead);
                             }
-                            if (creature == wolftype) {
+                            if (PersonType::types[creature].hasClaws) {
                                 emit_sound_at(clawslicesound, victim->coords, 128.);
                                 victim->spurt = 1;
                                 victim->DoBloodBig(2 / victim->armorhead, 175);
@@ -3471,7 +3358,7 @@ void Person::DoAnimations()
                             }
                             victim->Puff(abdomen);
                             victim->DoDamage(damagemult * 30 / victim->protectionhigh);
-                            if (creature == wolftype) {
+                            if (PersonType::types[creature].hasClaws) {
                                 emit_sound_at(clawslicesound, victim->coords, 128.);
                                 victim->spurt = 1;
                                 victim->DoBloodBig(2 / victim->armorhigh, 170);
@@ -3480,7 +3367,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                if (animCurrent == sweepanim && currentFrame().label == 5) {
                     if ((victim->animTarget != jumpupanim) &&
                         (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
                         (victim != this->shared_from_this())) {
@@ -3542,7 +3429,7 @@ void Person::DoAnimations()
                 }
             }
             if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
-                if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
+                if (animCurrent == spinkickreversalanim && currentFrame().label == 7) {
                     escapednum = 0;
                     if (id == 0) {
                         camerashake += .4;
@@ -3554,7 +3441,7 @@ void Person::DoAnimations()
                     if (!Tutorial::active) {
                         emit_sound_at(heavyimpactsound, victim->coords, 128.);
                     }
-                    if (creature == wolftype) {
+                    if (PersonType::types[creature].hasClaws) {
                         emit_sound_at(clawslicesound, victim->coords, 128);
                         victim->spurt = 1;
                         victim->DoBloodBig(2 / victim->armorhigh, 170);
@@ -3575,7 +3462,7 @@ void Person::DoAnimations()
                 }
 
                 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
-                    if (victim->weaponactive != -1 && victim->num_weapons > 0) {
+                    if (victim->hasWeapon() && victim->num_weapons > 0) {
                         if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
                             takeWeapon(victim->weaponids[victim->weaponactive]);
                             victim->num_weapons--;
@@ -3587,7 +3474,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                if (animCurrent == staffhitreversalanim && currentFrame().label == 5) {
                     escapednum = 0;
                     if (id == 0) {
                         camerashake += .4;
@@ -3610,7 +3497,7 @@ void Person::DoAnimations()
                     victim->DoDamage(damagemult * 70 / victim->protectionhigh);
                 }
 
-                if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
+                if (animCurrent == staffspinhitreversalanim && currentFrame().label == 7) {
                     escapednum = 0;
                     if (id == 0) {
                         camerashake += .4;
@@ -3640,7 +3527,7 @@ void Person::DoAnimations()
                     victim->DoDamage(damagemult * 70 / victim->protectionhigh);
                 }
 
-                if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
+                if (animCurrent == upunchreversalanim && currentFrame().label == 7) {
                     escapednum = 0;
                     victim->RagDoll(1);
                     XYZ relative;
@@ -3666,17 +3553,17 @@ void Person::DoAnimations()
                     award_bonus(id, Reversal);
 
                     bool doslice;
-                    doslice = 0;
-                    if (weaponactive != -1 || creature == wolftype) {
-                        doslice = 1;
-                    }
-                    if (creature == rabbittype && weaponactive != -1) {
-                        if (weapons[weaponids[0]].getType() == staff) {
-                            doslice = 0;
-                        }
+                    if (hasWeapon()) {
+                        doslice = (weapons[weaponids[0]].getType() != staff);
+                    } else {
+                        doslice = PersonType::types[creature].hasClaws;
                     }
                     if (doslice) {
-                        if (weaponactive != -1) {
+                        if (!hasWeapon()) {
+                            emit_sound_at(clawslicesound, victim->coords, 128.);
+                            victim->spurt = 1;
+                            victim->DoBloodBig(2 / victim->armorhigh, 175);
+                        } else {
                             victim->DoBloodBig(2 / victim->armorhigh, 225);
                             emit_sound_at(knifeslicesound, victim->coords);
                             if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
@@ -3684,15 +3571,10 @@ 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);
-                        }
                     }
                 }
 
-                if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
+                if (animCurrent == swordslashreversalanim && currentFrame().label == 7) {
                     escapednum = 0;
                     victim->RagDoll(1);
                     XYZ relative;
@@ -3715,7 +3597,7 @@ void Person::DoAnimations()
                     award_bonus(id, swordreversebonus);
                 }
 
-                if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
+                if (hasvictim && animCurrent == knifeslashreversalanim && currentFrame().label == 7) {
                     escapednum = 0;
                     if (id == 0) {
                         camerashake += .4;
@@ -3743,7 +3625,7 @@ void Person::DoAnimations()
                     award_bonus(id, Reversal);
                 }
 
-                if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
+                if (hasvictim && animCurrent == sneakattackanim && currentFrame().label == 7) {
                     escapednum = 0;
                     victim->RagDoll(0);
                     victim->skeleton.spinny = 0;
@@ -3760,17 +3642,17 @@ void Person::DoAnimations()
                     victim->damage = victim->damagetolerance;
                     victim->permanentdamage = victim->damagetolerance - 1;
                     bool doslice;
-                    doslice = 0;
-                    if (weaponactive != -1 || creature == wolftype) {
-                        doslice = 1;
-                    }
-                    if (creature == rabbittype && weaponactive != -1) {
-                        if (weapons[weaponids[0]].getType() == staff) {
-                            doslice = 0;
-                        }
+                    if (hasWeapon()) {
+                        doslice = (weapons[weaponids[0]].getType() != staff);
+                    } else {
+                        doslice = PersonType::types[creature].hasClaws;
                     }
                     if (doslice) {
-                        if (weaponactive != -1) {
+                        if (!hasWeapon()) {
+                            emit_sound_at(clawslicesound, victim->coords, 128.);
+                            victim->spurt = 1;
+                            victim->DoBloodBig(2, 175);
+                        } else {
                             victim->DoBloodBig(200, 225);
                             emit_sound_at(knifeslicesound, victim->coords);
                             if (bloodtoggle) {
@@ -3778,18 +3660,12 @@ void Person::DoAnimations()
                             }
                             weapons[weaponids[weaponactive]].blooddrip += 5;
                         }
-
-                        if (creature == wolftype && weaponactive == -1) {
-                            emit_sound_at(clawslicesound, victim->coords, 128.);
-                            victim->spurt = 1;
-                            victim->DoBloodBig(2, 175);
-                        }
                     }
                     award_bonus(id, spinecrusher);
                 }
 
-                if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
-                    if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
+                if (hasvictim && (animCurrent == knifefollowanim || animCurrent == knifesneakattackanim) && currentFrame().label == 5) {
+                    if (hasWeapon() && victim->bloodloss < victim->damagetolerance) {
                         escapednum = 0;
                         if (animTarget == knifefollowanim) {
                             victim->DoBloodBig(200, 210);
@@ -3833,7 +3709,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
+                if (hasvictim && (animCurrent == knifefollowanim || animCurrent == knifesneakattackanim) && currentFrame().label == 6) {
                     escapednum = 0;
                     victim->velocity = 0;
                     for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
@@ -3845,7 +3721,7 @@ void Person::DoAnimations()
                             victim->skeleton.joints[i].velocity = 0;
                         }
                     }
-                    if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
+                    if (hasWeapon() && Animation::animations[victim->animTarget].attack != reversal) {
                         emit_sound_at(fleshstabremovesound, victim->coords);
                         if (bloodtoggle) {
                             weapons[weaponids[weaponactive]].bloody = 2;
@@ -3866,8 +3742,8 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
-                    if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
+                if (hasvictim && (animCurrent == swordsneakattackanim) && currentFrame().label == 5) {
+                    if (hasWeapon() && victim->bloodloss < victim->damagetolerance) {
                         award_bonus(id, backstab);
 
                         escapednum = 0;
@@ -3895,13 +3771,13 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
+                if (hasvictim && animCurrent == swordsneakattackanim && currentFrame().label == 6) {
                     escapednum = 0;
                     victim->velocity = 0;
                     for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
                         victim->skeleton.joints[i].velocity = 0;
                     }
-                    if (weaponactive != -1) {
+                    if (hasWeapon()) {
                         emit_sound_at(fleshstabremovesound, victim->coords);
                         if (bloodtoggle) {
                             weapons[weaponids[weaponactive]].bloody = 2;
@@ -3922,7 +3798,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
+                if (animCurrent == sweepreversalanim && currentFrame().label == 7) {
                     escapednum = 0;
                     if (id == 0) {
                         camerashake += .4;
@@ -3931,23 +3807,23 @@ void Person::DoAnimations()
                         victim->spurt = 1;
                         DoBlood(.2, 240);
                     }
-                    if (weaponactive == -1) {
+                    if (!hasWeapon()) {
                         if (!Tutorial::active) {
                             emit_sound_at(heavyimpactsound, victim->coords, 128.);
                         }
                     }
                     bool doslice;
-                    doslice = 0;
-                    if (weaponactive != -1 || creature == wolftype) {
-                        doslice = 1;
-                    }
-                    if (creature == rabbittype && weaponactive != -1) {
-                        if (weapons[weaponids[0]].getType() == staff) {
-                            doslice = 0;
-                        }
+                    if (hasWeapon()) {
+                        doslice = (weapons[weaponids[0]].getType() != staff);
+                    } else {
+                        doslice = PersonType::types[creature].hasClaws;
                     }
                     if (doslice) {
-                        if (weaponactive != -1) {
+                        if (!hasWeapon()) {
+                            emit_sound_at(clawslicesound, victim->coords, 128.);
+                            victim->spurt = 1;
+                            victim->DoBloodBig(2 / victim->armorhead, 175);
+                        } else {
                             victim->DoBloodBig(2 / victim->armorhead, 225);
                             emit_sound_at(knifeslicesound, victim->coords);
                             if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
@@ -3955,11 +3831,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->armorhead, 175);
-                        }
                     }
 
                     award_bonus(id, Reversal);
@@ -3984,7 +3855,7 @@ void Person::DoAnimations()
                     victim->velocity = 0;
                 }
 
-                if (animTarget == sweepreversalanim && ((Animation::animations[animTarget].frames[frameCurrent].label == 9 && victim->damage < victim->damagetolerance) || (Animation::animations[animTarget].frames[frameCurrent].label == 7 && victim->damage > victim->damagetolerance))) {
+                if (animCurrent == sweepreversalanim && ((currentFrame().label == 9 && victim->damage < victim->damagetolerance) || (currentFrame().label == 7 && victim->damage > victim->damagetolerance))) {
                     escapednum = 0;
                     victim->RagDoll(0);
                     XYZ relative;
@@ -4008,7 +3879,7 @@ void Person::DoAnimations()
             }
 
             //Animation end
-            if (frameTarget > int(Animation::animations[animCurrent].frames.size()) - 1) {
+            if (frameTarget >= int(Animation::animations[animCurrent].frames.size())) {
                 frameTarget = 0;
                 if (wasStop()) {
                     animTarget = getIdle();
@@ -4046,8 +3917,9 @@ void Person::DoAnimations()
                     if (animCurrent == crouchdrawrightanim) {
                         animTarget = getCrouch();
                     }
-                    if (weaponactive == -1) {
+                    if (!hasWeapon()) {
                         weaponactive = 0;
+                        emit_sound_at(knifedrawsound, coords, 128.);
                     } else if (weaponactive == 0) {
                         weaponactive = -1;
                         if (num_weapons == 2) {
@@ -4056,14 +3928,8 @@ void Person::DoAnimations()
                             weaponids[0] = weaponids[1];
                             weaponids[1] = buffer;
                         }
-                    }
-
-                    if (weaponactive == -1) {
                         emit_sound_at(knifesheathesound, coords, 128.);
                     }
-                    if (weaponactive != -1) {
-                        emit_sound_at(knifedrawsound, coords, 128.);
-                    }
                 }
                 if (animCurrent == rollanim) {
                     animTarget = getCrouch();
@@ -4417,7 +4283,7 @@ void Person::DoAnimations()
                     animTarget = getIdle();
                     lastfeint = 0;
                 }
-                if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
+                if (animCurrent == blockhighleftanim && !isPlayerControlled()) {
                     animTarget = blockhighleftstrikeanim;
                 }
                 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
@@ -4481,6 +4347,11 @@ void Person::DoAnimations()
                 frameCurrent = frameTarget;
                 target = 1;
             }
+
+            if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
+                frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
+            }
+
             oldrot = rot;
             rot = targetrot * target;
             yaw += rot - oldrot;
@@ -4489,9 +4360,7 @@ void Person::DoAnimations()
                 oldrot = 0;
                 targetrot = 0;
             }
-            if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
-                frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
-            }
+
             if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
                 //Old rotates
                 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
@@ -4636,7 +4505,7 @@ void Person::DoStuff()
         targetoffset = 0;
     }
 
-    if (num_weapons == 1 && weaponactive != -1) {
+    if (num_weapons == 1 && hasWeapon()) {
         weaponstuck = -1;
     }
 
@@ -4683,7 +4552,7 @@ void Person::DoStuff()
             frameTarget = 0;
         }
     }
-    if (weaponactive == -1 && num_weapons > 0) {
+    if (!hasWeapon() && num_weapons > 0) {
         if (weapons[weaponids[0]].getType() == staff) {
             weaponactive = 0;
         }
@@ -4795,7 +4664,7 @@ void Person::DoStuff()
             deathbleeding = 0;
         }
         if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
-            if (weaponactive != -1) {
+            if (hasWeapon()) {
                 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
                 weapons[weaponids[0]].velocity.x += .01;
                 num_weapons--;
@@ -5226,7 +5095,7 @@ void Person::DoStuff()
 
         RagDoll(0);
 
-        if (weaponactive != -1) {
+        if (hasWeapon()) {
             weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
             weapons[weaponids[0]].velocity.x += .01;
             num_weapons--;
@@ -5283,7 +5152,7 @@ void Person::DoStuff()
     if (permanentdamage > damagetolerance && dead != 2) {
         DoBlood(1, 255);
 
-        if (weaponactive != -1) {
+        if (hasWeapon()) {
             weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
             weapons[weaponids[0]].velocity.x += .01;
             num_weapons--;
@@ -5817,7 +5686,7 @@ void Person::DoStuff()
         if (Tutorial::active && id != 0) {
             play = 0;
         }
-        if (play && aitype != playercontrolled) {
+        if (play && !isPlayerControlled()) {
             int whichsound = -1;
             if (speechdelay <= 0) {
                 unsigned int i = abs(Random() % 4);
@@ -6003,7 +5872,7 @@ void Person::DoStuff()
             }
         }
 
-        if (weaponactive != -1) {
+        if (hasWeapon()) {
             if (weapons[weaponids[weaponactive]].getType() != staff) {
                 righthandmorphstart = 1;
                 righthandmorphend = 1;
@@ -6127,19 +5996,10 @@ void Person::DoStuff()
         } else if (isRun()) {
             velocity += facing * multiplier * speed * 700 * scale;
             velspeed = findLength(&velocity);
-            if (creature == rabbittype) {
-                if (velspeed > speed * 55 * scale) {
-                    velocity /= velspeed;
-                    velspeed = speed * 55 * scale;
-                    velocity *= velspeed;
-                }
-            }
-            if (creature == wolftype) {
-                if (velspeed > speed * 75 * scale) {
-                    velocity /= velspeed;
-                    velspeed = speed * 75 * scale;
-                    velocity *= velspeed;
-                }
+            if (velspeed > speed * PersonType::types[creature].maxRunSpeed * scale) {
+                velocity /= velspeed;
+                velspeed = speed * PersonType::types[creature].maxRunSpeed * scale;
+                velocity *= velspeed;
             }
             velocity.y += gravity * multiplier * 20;
             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
@@ -6611,24 +6471,24 @@ int Person::DrawSkeleton()
                             glMatrixMode(GL_MODELVIEW);
                             glPushMatrix();
                             if (p1 == abdomen || p2 == abdomen) {
-                                glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(1).x,
-                                             (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(1).y,
-                                             (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(1).z);
+                                glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(1).x,
+                                             (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(1).y,
+                                             (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(1).z);
                             }
                             if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
-                                glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(2).x,
-                                             (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(2).y,
-                                             (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(2).z);
+                                glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(2).x,
+                                             (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(2).y,
+                                             (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(2).z);
                             }
                             if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
-                                glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(3).x,
-                                             (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(3).y,
-                                             (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(3).z);
+                                glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(3).x,
+                                             (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(3).y,
+                                             (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(3).z);
                             }
                             if (p1 == head || p2 == head) {
-                                glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(0).x,
-                                             (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(0).y,
-                                             (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(0).z);
+                                glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(0).x,
+                                             (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(0).y,
+                                             (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(0).z);
                             }
                             glGetFloatv(GL_MODELVIEW_MATRIX, M);
                             skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
@@ -6643,24 +6503,24 @@ int Person::DrawSkeleton()
                             glMatrixMode(GL_MODELVIEW);
                             glPushMatrix();
                             if (p1 == abdomen || p2 == abdomen) {
-                                glTranslatef(v0.x * getProportion(1).x,
-                                             v0.y * getProportion(1).y,
-                                             v0.z * getProportion(1).z);
+                                glTranslatef(v0.x * getProportionXYZ(1).x,
+                                             v0.y * getProportionXYZ(1).y,
+                                             v0.z * getProportionXYZ(1).z);
                             }
                             if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
-                                glTranslatef(v0.x * getProportion(2).x,
-                                             v0.y * getProportion(2).y,
-                                             v0.z * getProportion(2).z);
+                                glTranslatef(v0.x * getProportionXYZ(2).x,
+                                             v0.y * getProportionXYZ(2).y,
+                                             v0.z * getProportionXYZ(2).z);
                             }
                             if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
-                                glTranslatef(v0.x * getProportion(3).x,
-                                             v0.y * getProportion(3).y,
-                                             v0.z * getProportion(3).z);
+                                glTranslatef(v0.x * getProportionXYZ(3).x,
+                                             v0.y * getProportionXYZ(3).y,
+                                             v0.z * getProportionXYZ(3).z);
                             }
                             if (p1 == head || p2 == head) {
-                                glTranslatef(v0.x * getProportion(0).x,
-                                             v0.y * getProportion(0).y,
-                                             v0.z * getProportion(0).z);
+                                glTranslatef(v0.x * getProportionXYZ(0).x,
+                                             v0.y * getProportionXYZ(0).y,
+                                             v0.z * getProportionXYZ(0).z);
                             }
 
                             glGetFloatv(GL_MODELVIEW_MATRIX, M);
@@ -6699,24 +6559,24 @@ int Person::DrawSkeleton()
                         glMatrixMode(GL_MODELVIEW);
                         glPushMatrix();
                         if (p1 == abdomen || p2 == abdomen) {
-                            glTranslatef(v0.x * getProportion(1).x,
-                                         v0.y * getProportion(1).y,
-                                         v0.z * getProportion(1).z);
+                            glTranslatef(v0.x * getProportionXYZ(1).x,
+                                         v0.y * getProportionXYZ(1).y,
+                                         v0.z * getProportionXYZ(1).z);
                         }
                         if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
-                            glTranslatef(v0.x * getProportion(2).x,
-                                         v0.y * getProportion(2).y,
-                                         v0.z * getProportion(2).z);
+                            glTranslatef(v0.x * getProportionXYZ(2).x,
+                                         v0.y * getProportionXYZ(2).y,
+                                         v0.z * getProportionXYZ(2).z);
                         }
                         if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
-                            glTranslatef(v0.x * getProportion(3).x,
-                                         v0.y * getProportion(3).y,
-                                         v0.z * getProportion(3).z);
+                            glTranslatef(v0.x * getProportionXYZ(3).x,
+                                         v0.y * getProportionXYZ(3).y,
+                                         v0.z * getProportionXYZ(3).z);
                         }
                         if (p1 == head || p2 == head) {
-                            glTranslatef(v0.x * getProportion(0).x,
-                                         v0.y * getProportion(0).y,
-                                         v0.z * getProportion(0).z);
+                            glTranslatef(v0.x * getProportionXYZ(0).x,
+                                         v0.y * getProportionXYZ(0).y,
+                                         v0.z * getProportionXYZ(0).z);
                         }
                         glGetFloatv(GL_MODELVIEW_MATRIX, M);
                         skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
@@ -7465,7 +7325,7 @@ bool Person::addClothes(const int& clothesId)
 
 void Person::doAI()
 {
-    if (aitype != playercontrolled && !Dialog::inDialog()) {
+    if (!isPlayerControlled() && !isPlayerFriend() && !Dialog::inDialog()) {
         jumpclimb = 0;
         //disable movement in editor
         if (Game::editorenabled) {
@@ -8138,7 +7998,7 @@ void Person::doAI()
                 lastseentime = 12;
 
                 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile)) {
-                    if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) {
+                    if (ally < 0 || hasWeapon() || lastchecktime <= 0) {
                         aitype = attacktypecutoff;
                         lastseentime = 1;
                     }
@@ -8210,7 +8070,7 @@ void Person::doAI()
                     if (isIdle()) {
                         crouchkeydown = 1;
                     }
-                    if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
+                    if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->hasWeapon()) {
                         if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
                             if (isIdle() || isCrouch() || isRun() || isFlip()) {
                                 if (abs(Random() % 2) == 0) {
@@ -8324,7 +8184,7 @@ void Person::doAI()
                 animTarget != backhandspringanim &&
                 animTarget != dodgebackanim) {
                 //draw weapon
-                if (weaponactive == -1 && num_weapons > 0) {
+                if (!hasWeapon() && num_weapons > 0) {
                     drawkeydown = Random() % 2;
                 } else {
                     drawkeydown = 0;
@@ -8343,11 +8203,11 @@ void Person::doAI()
                 lookyaw = targetyaw;
                 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
 
-                if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1)) {
+                if (distsq(&coords, &Person::players[0]->coords) > 5 && (!Person::players[0]->hasWeapon() || hasWeapon())) {
                     forwardkeydown = 1;
                 } else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
                             distsq(&coords, &Person::players[0]->coords) < 9) &&
-                           Person::players[0]->weaponactive != -1) {
+                           Person::players[0]->hasWeapon()) {
                     forwardkeydown = 1;
                 } else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0)) {
                     forwardkeydown = 1;
@@ -8381,7 +8241,7 @@ void Person::doAI()
                     targetyaw += 90 * (whichdirection * 2 - 1);
                 }
                 //attack!!!
-                if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype) {
+                if (Random() % 2 == 0 || hasWeapon() || creature == wolftype) {
                     attackkeydown = 1;
                 } else {
                     attackkeydown = 0;
@@ -8391,7 +8251,7 @@ void Person::doAI()
                 }
 
                 //TODO: wat
-                if (aitype != playercontrolled &&
+                if (!isPlayerControlled() &&
                     (isIdle() ||
                      isCrouch() ||
                      isRun())) {
@@ -8407,9 +8267,9 @@ void Person::doAI()
                                  Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
                                  (Random() % 2 == 0 || difficulty == 2) ||
                              (isIdle() || isRun()) &&
-                                 Person::players[j]->weaponactive != -1 ||
+                                 Person::players[j]->hasWeapon() ||
                              Person::players[j]->animTarget == swordslashanim &&
-                                 weaponactive != -1 ||
+                                 hasWeapon() ||
                              Person::players[j]->animTarget == staffhitanim ||
                              Person::players[j]->animTarget == staffspinhitanim)) {
                             if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
@@ -8424,7 +8284,7 @@ void Person::doAI()
                                  Person::players[j]->animTarget == knifeslashstartanim ||
                                  Person::players[j]->animTarget == swordslashanim &&
                                      (distsq(&Person::players[j]->coords, &coords) < 2 ||
-                                      weaponactive != -1))) {
+                                      hasWeapon()))) {
                                 if (target >= 0) {
                                     target = -1;
                                 } else {
@@ -8544,3 +8404,10 @@ void Person::doAI()
         }
     }
 }
+
+bool Person::catchKnife()
+{
+    return
+        ((PersonType::types[creature].knifeCatchingType == 0) && (Random() % 2 != 0) && (!hasWeapon()) && (aitype == attacktypecutoff)) ||
+        ((PersonType::types[creature].knifeCatchingType == 1) && (Random() % 3 != 0) && (!hasWeapon()) && (isIdle() || isRun() || animTarget == walkanim));
+}