]> git.jsancho.org Git - lugaru.git/blobdiff - Source/Objects/Person.cpp
Added hasClaws property for PersonType
[lugaru.git] / Source / Objects / Person.cpp
index 817ee03734268e777c76543571c2faa279e51c0b..ff699a1cae6109729496d30d7a3f06130250d029 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)
@@ -446,17 +336,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,19 +427,25 @@ 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::changeCreatureType(person_type type)
+{
+    creature = type;
+    whichskin = 0;
+    skeletonLoad(type == rabbittype);
+    scale = PersonType::types[creature].defaultScale;
+    damagetolerance = PersonType::types[creature].defaultDamageTolerance;
+}
+
 void Person::skeletonLoad(bool clothes)
 {
     skeleton.id = id;
@@ -581,7 +475,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 +501,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);
@@ -2191,8 +2090,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;
@@ -2334,7 +2232,7 @@ 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) {
@@ -2350,7 +2248,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) {
@@ -2436,7 +2334,7 @@ void Person::DoAnimations()
                 }
             }
 
-            if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+            if (animCurrent == drawleftanim && currentFrame().label == 5) {
                 if (weaponactive == -1) {
                     weaponactive = 0;
                 } else if (weaponactive == 0) {
@@ -2536,31 +2434,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 +2477,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 +2512,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 +2523,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 +2549,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 +2560,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 +2586,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 +2611,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 +2646,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 +2672,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 +2714,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 +2811,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 +2915,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 +2953,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 +3000,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,7 +3011,7 @@ 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;
@@ -3141,7 +3036,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                if (animCurrent == knifethrowanim && currentFrame().label == 5) {
                     if (weaponactive != -1) {
                         escapednum = 0;
                         XYZ aim;
@@ -3156,9 +3051,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);
@@ -3213,7 +3108,7 @@ 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)) {
                             award_bonus(id, Slashbonus);
@@ -3298,7 +3193,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 +3201,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 +3228,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 +3236,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 +3261,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 +3271,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 +3313,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 +3344,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 +3366,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 +3375,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 +3437,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 +3449,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);
@@ -3587,7 +3482,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 +3505,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 +3535,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 +3561,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 (weaponactive == -1) {
+                        doslice = PersonType::types[creature].hasClaws;
+                    } else {
+                        doslice = (weapons[weaponids[0]].getType() != staff);
                     }
                     if (doslice) {
-                        if (weaponactive != -1) {
+                        if (weaponactive == -1) {
+                            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 +3579,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 +3605,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 +3633,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 +3650,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 (weaponactive == -1) {
+                        doslice = PersonType::types[creature].hasClaws;
+                    } else {
+                        doslice = (weapons[weaponids[0]].getType() != staff);
                     }
                     if (doslice) {
-                        if (weaponactive != -1) {
+                        if (weaponactive == -1) {
+                            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,17 +3668,11 @@ 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 (hasvictim && (animCurrent == knifefollowanim || animCurrent == knifesneakattackanim) && currentFrame().label == 5) {
                     if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
                         escapednum = 0;
                         if (animTarget == knifefollowanim) {
@@ -3833,7 +3717,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++) {
@@ -3866,7 +3750,7 @@ void Person::DoAnimations()
                     }
                 }
 
-                if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
+                if (hasvictim && (animCurrent == swordsneakattackanim) && currentFrame().label == 5) {
                     if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
                         award_bonus(id, backstab);
 
@@ -3895,7 +3779,7 @@ 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++) {
@@ -3922,7 +3806,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;
@@ -3937,17 +3821,17 @@ void Person::DoAnimations()
                         }
                     }
                     bool doslice;
-                    doslice = 0;
-                    if (weaponactive != -1 || creature == wolftype) {
-                        doslice = 1;
-                    }
-                    if (creature == rabbittype && weaponactive != -1) {
-                        if (weapons[weaponids[0]].getType() == staff) {
-                            doslice = 0;
-                        }
+                    if (weaponactive == -1) {
+                        doslice = PersonType::types[creature].hasClaws;
+                    } else {
+                        doslice = (weapons[weaponids[0]].getType() != staff);
                     }
                     if (doslice) {
-                        if (weaponactive != -1) {
+                        if (weaponactive == -1) {
+                            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 +3839,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 +3863,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 +3887,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();
@@ -4481,6 +4360,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 +4373,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++) {
@@ -6611,24 +6493,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 +6525,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 +6581,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;