2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
21 #include "Objects/Person.hpp"
23 #include "Animation/Animation.hpp"
24 #include "Audio/Sounds.hpp"
25 #include "Audio/openal_wrapper.hpp"
27 #include "Level/Awards.hpp"
28 #include "Level/Dialog.hpp"
29 #include "Tutorial.hpp"
30 #include "Utils/Folders.hpp"
32 extern float multiplier;
33 extern Terrain terrain;
35 extern int environment;
37 extern FRUSTUM frustum;
39 extern float realmultiplier;
41 extern float slomodelay;
42 extern bool cellophane;
43 extern float texdetail;
44 extern float realtexdetail;
45 extern GLubyte bloodText[512 * 512 * 3];
46 extern GLubyte wolfbloodText[512 * 512 * 3];
47 extern int bloodtoggle;
48 extern bool autoslomo;
49 extern float camerashake;
51 extern float viewdistance;
52 extern float blackout;
53 extern int difficulty;
54 extern bool decalstoggle;
55 extern float fadestart;
57 extern bool winfreeze;
58 extern bool showpoints;
59 extern bool immediate;
60 extern float smoketex;
61 extern bool reversaltrain;
62 extern bool canattack;
64 extern float damagedealt;
66 extern float hostiletime;
68 extern bool gamestarted;
70 extern XYZ envsound[30];
71 extern float envsoundvol[30];
72 extern int numenvsounds;
73 extern float envsoundlife[30];
75 extern XYZ windvector;
77 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
82 , animCurrent(bounceidleanim)
83 , animTarget(bounceidleanim)
90 , howactive(typeactive)
92 , superruntoggle(false)
135 , rabbitkickenabled(false)
149 , superpermanentdamage(0)
192 , normalsupdatedelay(0)
196 , forwardkeydown(false)
197 , forwardstogglekeydown(false)
198 , rightkeydown(false)
202 , jumptogglekeydown(false)
203 , crouchkeydown(false)
204 , crouchtogglekeydown(false)
206 , drawtogglekeydown(false)
207 , throwkeydown(false)
208 , throwtogglekeydown(false)
209 , attackkeydown(false)
231 , whichdirection(false)
232 , whichdirectiondelay(0)
233 , avoidsomething(false)
243 , lefthandmorphness(0)
244 , righthandmorphness(0)
248 , targetlefthandmorphness(0)
249 , targetrighthandmorphness(0)
250 , targetheadmorphness(1)
251 , targetchestmorphness(0)
252 , targettailmorphness(0)
253 , lefthandmorphstart(0)
254 , lefthandmorphend(0)
255 , righthandmorphstart(0)
256 , righthandmorphend(0)
266 , highreversaldelay(0)
267 , lowreversaldelay(0)
316 , weaponstuckwhere(0)
329 , finalpathfindpoint(0)
330 , targetpathfindpoint(0)
331 , lastpathfindpoint(0)
332 , lastpathfindpoint2(0)
333 , lastpathfindpoint3(0)
334 , lastpathfindpoint4(0)
354 , neckspurtparticledelay(0)
359 , rabbitkickragdoll(false)
369 /* Read a person in tfile. Throws an error if it’s not valid */
370 Person::Person(FILE* tfile, int mapvers, unsigned i)
374 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
376 funpackf(tfile, "Bi", &howactive);
378 howactive = typeactive;
381 funpackf(tfile, "Bf", &scale);
386 funpackf(tfile, "Bb", &immobile);
391 funpackf(tfile, "Bf", &yaw);
396 if (num_weapons < 0 || num_weapons > 5) {
397 throw InvalidPersonException();
399 if (num_weapons > 0 && num_weapons < 5) {
400 for (int j = 0; j < num_weapons; j++) {
401 weaponids[j] = weapons.size();
403 funpackf(tfile, "Bi", &type);
404 weapons.push_back(Weapon(type, id));
407 funpackf(tfile, "Bi", &numwaypoints);
408 for (int j = 0; j < numwaypoints; j++) {
409 funpackf(tfile, "Bf", &waypoints[j].x);
410 funpackf(tfile, "Bf", &waypoints[j].y);
411 funpackf(tfile, "Bf", &waypoints[j].z);
413 funpackf(tfile, "Bi", &waypointtype[j]);
415 waypointtype[j] = wpkeepwalking;
419 funpackf(tfile, "Bi", &waypoint);
420 if (waypoint > (numwaypoints - 1)) {
424 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
425 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
426 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
427 funpackf(tfile, "Bf Bf", &power, &speedmult);
429 float headprop, legprop, armprop, bodyprop;
432 funpackf(tfile, "Bf Bf Bf Bf", &headprop, &bodyprop, &armprop, &legprop);
440 if (creature == wolftype) {
441 proportionhead = 1.1 * headprop;
442 proportionbody = 1.1 * bodyprop;
443 proportionarms = 1.1 * armprop;
444 proportionlegs = 1.1 * legprop;
445 } else if (creature == rabbittype) {
446 proportionhead = 1.2 * headprop;
447 proportionbody = 1.05 * bodyprop;
448 proportionarms = 1.00 * armprop;
449 proportionlegs = 1.1 * legprop;
450 proportionlegs.y = 1.05 * legprop;
453 funpackf(tfile, "Bi", &numclothes);
454 for (int k = 0; k < numclothes; k++) {
456 funpackf(tfile, "Bi", &templength);
457 for (int l = 0; l < templength; l++)
458 funpackf(tfile, "Bb", &clothes[k][l]);
459 clothes[k][templength] = '\0';
460 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
466 if (creature == wolftype) {
468 damagetolerance = 300;
475 realoldcoords = coords;
478 void Person::skeletonLoad(bool clothes)
481 if (creature != wolftype) {
483 "Skeleton/BasicFigure",
484 "Skeleton/BasicFigureLow",
485 "Skeleton/RabbitBelt",
487 "Models/Body2.solid",
488 "Models/Body3.solid",
489 "Models/Body4.solid",
490 "Models/Body5.solid",
491 "Models/Body6.solid",
492 "Models/Body7.solid",
493 "Models/BodyLow.solid",
498 "Skeleton/BasicFigureWolf",
499 "Skeleton/BasicFigureWolfLow",
500 "Skeleton/RabbitBelt",
502 "Models/Wolf2.solid",
503 "Models/Wolf3.solid",
504 "Models/Wolf4.solid",
505 "Models/Wolf5.solid",
506 "Models/Wolf6.solid",
507 "Models/Wolf7.solid",
508 "Models/WolfLow.solid",
513 skeleton.drawmodel.textureptr.load(creatureskin[creature][whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
519 * GameTick/doPlayerCollisions
521 void Person::CheckKick()
523 if (!(hasvictim && (animTarget == rabbitkickanim && victim && victim != this->shared_from_this() && frameCurrent >= 2 && animCurrent == rabbitkickanim) && distsq(&coords, &victim->coords) < 1.2 && !victim->skeleton.free))
526 if (Animation::animations[victim->animTarget].height != lowheight) {
527 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
528 XYZ relative = velocity;
530 Normalise(&relative);
534 if (!Tutorial::active)
535 emit_sound_at(heavyimpactsound, victim->coords);
537 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
538 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
541 victim->DoDamage(100 * damagemult / victim->protectionhigh);
547 animTarget = backflipanim;
549 velocity = facing * -10;
553 resume_stream(whooshsound);
555 award_bonus(id, cannon);
556 } else if (victim->isCrouch()) {
557 animTarget = rabbitkickreversedanim;
558 animCurrent = rabbitkickreversedanim;
559 victim->animCurrent = rabbitkickreversalanim;
560 victim->animTarget = rabbitkickreversalanim;
566 victim->oldcoords = victim->coords;
567 coords = victim->coords;
568 victim->targetyaw = targetyaw;
569 victim->victim = this->shared_from_this();
576 * GameTick/doPlayerCollisions - spread fire between players
577 * GameTick/doDevKeys - press f to ignite
578 * Person::DoStuff - spread fire from lit campfires and bushes
580 void Person::CatchFire()
582 XYZ flatfacing, flatvelocity;
584 for (int i = 0; i < 10; i++) {
585 howmany = fabs(Random() % (skeleton.joints.size()));
587 flatvelocity = skeleton.joints[howmany].velocity;
588 flatfacing = skeleton.joints[howmany].position * scale + coords;
590 flatvelocity = velocity;
591 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
593 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
598 emit_sound_at(firestartsound, coords);
600 emit_stream_at(stream_firesound, coords);
608 * idle animation for this creature (depending on status)
610 int Person::getIdle()
612 if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype))
614 if (hasvictim && (victim != this->shared_from_this())) {
615 if ((!victim->dead && victim->aitype != passivetype &&
616 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
617 victim->id < Person::players.size())) {
618 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
619 if (creature == rabbittype)
620 return fightidleanim;
621 if (creature == wolftype)
624 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
625 if (weapons[weaponids[weaponactive]].getType() == knife)
626 return knifefightidleanim;
627 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
628 return swordfightidlebothanim;
629 if (weapons[weaponids[weaponactive]].getType() == sword)
630 return swordfightidleanim;
631 if (weapons[weaponids[weaponactive]].getType() == staff)
632 return swordfightidleanim;
634 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
635 return fightsidestep;
638 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
640 if (howactive == typesitting)
642 if (howactive == typesittingwall)
644 if (howactive == typesleeping)
646 if (howactive == typedead1)
648 if (howactive == typedead2)
650 if (howactive == typedead3)
652 if (howactive == typedead4)
654 if (creature == rabbittype)
655 return bounceidleanim;
656 if (creature == wolftype)
662 * crouch animation for this creature
664 int Person::getCrouch()
666 if (creature == rabbittype)
668 if (creature == wolftype)
669 return wolfcrouchanim;
674 * running animation for this creature (can be upright or all fours)
678 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
680 if (creature == wolftype && (!superruntoggle))
683 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
684 return rabbitrunninganim;
685 if (creature == wolftype && (superruntoggle))
686 return wolfrunninganim;
692 int Person::getStop()
694 if (creature == rabbittype)
696 if (creature == wolftype)
703 int Person::getLanding()
705 if (creature == rabbittype)
707 if (creature == wolftype)
714 int Person::getLandhard()
716 if (creature == rabbittype)
718 if (creature == wolftype)
719 return wolflandhardanim;
726 * Person::DoAnimations
729 SolidHitBonus(int playerid)
731 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
732 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
734 award_bonus(playerid, solidhit);
738 * spawns blood effects
740 void Person::DoBlood(float howmuch, int which)
742 // FIXME: should abstract out inputs
743 static int bleedxint, bleedyint;
745 if (bloodtoggle && !Tutorial::active) {
746 if (bleeding <= 0 && spurt) {
748 for (int i = 0; i < 3; i++) {
749 // emit blood particles
752 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
753 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
754 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
755 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
758 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
759 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
760 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
761 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
764 if (Random() % 2 == 0) // 50% chance
765 for (int i = 0; i < 3; i++) {
766 if (Random() % 2 != 0) {
767 // emit teeth particles
770 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
771 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
774 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
775 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
779 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
781 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
783 Sprite::setLastSpriteSpecial(3); // sets it to teeth
788 // FIXME: manipulating attributes
789 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
792 if (creature == rabbittype)
793 while (bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
794 bleedxint = abs(Random() % 512);
795 bleedyint = abs(Random() % 512);
797 if (creature == wolftype)
798 while (wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
799 bleedxint = abs(Random() % 512);
800 bleedyint = abs(Random() % 512);
804 bleedy /= realtexdetail;
805 bleedx /= realtexdetail;
806 direction = abs(Random() % 2) * 2 - 1;
814 * spawns big blood effects and ???
815 * modifies character's skin texture
817 void Person::DoBloodBig(float howmuch, int which)
819 static int bleedxint, bleedyint, i, j;
821 if (howmuch && id == 0)
824 if (!Tutorial::active || id == 0)
825 if (aitype != playercontrolled && howmuch > 0) {
829 if (creature == wolftype) {
830 int i = abs(Random() % 2);
832 whichsound = snarlsound;
834 whichsound = snarl2sound;
836 if (creature == rabbittype) {
837 int i = abs(Random() % 2);
839 whichsound = rabbitpainsound;
840 if (i == 1 && howmuch >= 2)
841 whichsound = rabbitpain1sound;
844 if (whichsound != -1) {
845 emit_sound_at(whichsound, coords);
850 if (id == 0 && howmuch > 0) {
854 if (bloodtoggle && decalstoggle && !Tutorial::active) {
855 if (bleeding <= 0 && spurt) {
857 for (int i = 0; i < 3; i++) {
858 // emit blood particles
859 // FIXME: copypaste from above
862 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
863 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
864 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
865 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
868 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
869 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
870 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
871 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
876 // weird texture manipulation code follows.
877 // looks like this is painting blood onto the character's skin texture
878 // FIXME: surely there's a better way
880 int offsetx = 0, offsety = 0;
882 offsety = Random() % 40;
883 offsetx = abs(Random() % 60);
885 if (which == 190 || which == 185) {
886 offsety = Random() % 40;
887 offsetx = abs(Random() % 100) - 20;
890 offsety = Random() % 10;
891 offsetx = Random() % 10;
894 offsety = Random() % 20;
895 offsetx = Random() % 20;
897 if (which == 220 || which == 215) {
906 if (creature == rabbittype)
907 for (i = 0; i < 512; i++) {
908 for (j = 0; j < 512; j++) {
909 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
921 if (creature == wolftype)
922 for (i = 0; i < 512; i++) {
923 for (j = 0; j < 512; j++) {
924 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
955 startx /= realtexdetail;
956 starty /= realtexdetail;
957 endx /= realtexdetail;
958 endy /= realtexdetail;
960 int texdetailint = realtexdetail;
962 if (creature == rabbittype)
963 for (i = startx; i < endx; i++) {
964 for (j = starty; j < endy; j++) {
965 if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
966 color = Random() % 85 + 170;
967 where = i * skeleton.skinsize * 3 + j * 3;
968 if (skeleton.skinText[where + 0] > color / 2)
969 skeleton.skinText[where + 0] = color / 2;
970 skeleton.skinText[where + 1] = 0;
971 skeleton.skinText[where + 2] = 0;
975 if (creature == wolftype)
976 for (i = startx; i < endx; i++) {
977 for (j = starty; j < endy; j++) {
978 if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
979 color = Random() % 85 + 170;
980 where = i * skeleton.skinsize * 3 + j * 3;
981 if (skeleton.skinText[where + 0] > color / 2)
982 skeleton.skinText[where + 0] = color / 2;
983 skeleton.skinText[where + 1] = 0;
984 skeleton.skinText[where + 2] = 0;
988 skeleton.drawmodel.textureptr.bind();
993 if (creature == rabbittype)
994 while (bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
995 bleedxint = abs(Random() % 512);
996 bleedyint = abs(Random() % 512);
998 if (creature == wolftype)
999 while (wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
1000 bleedxint = abs(Random() % 512);
1001 bleedyint = abs(Random() % 512);
1003 bleedy = bleedxint + offsetx;
1004 bleedx = bleedyint + offsety;
1005 bleedy /= realtexdetail;
1006 bleedx /= realtexdetail;
1011 if (bleedx > skeleton.skinsize - 1)
1012 bleedx = skeleton.skinsize - 1;
1013 if (bleedy > skeleton.skinsize - 1)
1014 bleedy = skeleton.skinsize - 1;
1015 direction = abs(Random() % 2) * 2 - 1;
1017 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1018 deathbleeding += bleeding;
1019 bloodloss += bleeding * 3;
1021 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1022 if (abs(Random() % 2) == 0) {
1023 aitype = gethelptype;
1026 aitype = attacktypecutoff;
1034 * similar to DoBloodBig
1036 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
1039 static XYZ bloodvel;
1040 static XYZ startpoint, endpoint, colpoint, movepoint;
1041 static float rotationpoint;
1042 static int whichtri;
1043 static XYZ p1, p2, p3, p0;
1046 float coordsx, coordsy;
1049 if (bloodtoggle && decalstoggle && !Tutorial::active) {
1052 where = DoRotation(where, 0, -yaw, 0);
1055 startpoint.y += 100;
1060 // ray testing for a tri in the character model
1061 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
1062 if (whichtri != -1) {
1063 // low level geometry math
1065 p1 = skeleton.drawmodel.getTriangleVertex(whichtri, 0);
1066 p2 = skeleton.drawmodel.getTriangleVertex(whichtri, 1);
1067 p3 = skeleton.drawmodel.getTriangleVertex(whichtri, 2);
1069 bary.x = distsq(&p0, &p1);
1070 bary.y = distsq(&p0, &p2);
1071 bary.z = distsq(&p0, &p3);
1073 total = bary.x + bary.y + bary.z;
1078 bary.x = 1 - bary.x;
1079 bary.y = 1 - bary.y;
1080 bary.z = 1 - bary.z;
1082 total = bary.x + bary.y + bary.z;
1087 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1088 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1089 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1090 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1091 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1092 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1093 coordsx = skeleton.drawmodel.Triangles[whichtri].gx[0] * bary.x + skeleton.drawmodel.Triangles[whichtri].gx[1] * bary.y + skeleton.drawmodel.Triangles[whichtri].gx[2] * bary.z;
1094 coordsy = skeleton.drawmodel.Triangles[whichtri].gy[0] * bary.x + skeleton.drawmodel.Triangles[whichtri].gy[1] * bary.y + skeleton.drawmodel.Triangles[whichtri].gy[2] * bary.z;
1096 if (bleeding <= 0 && spurt) {
1098 for (int i = 0; i < 3; i++) {
1099 // emit blood particles
1100 // FIXME: more copypaste code
1102 if (skeleton.free) {
1103 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1104 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1105 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1106 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1109 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1110 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1111 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1112 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1117 // texture manipulation follows
1119 int offsetx = 0, offsety = 0;
1120 offsetx = (1 + coordsy) * 512 - 291;
1121 offsety = coordsx * 512 - 437;
1128 if (creature == rabbittype)
1129 for (i = 0; i < 512; i++) {
1130 for (j = 0; j < 512; j++) {
1131 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1143 if (creature == wolftype)
1144 for (i = 0; i < 512; i++) {
1145 for (j = 0; j < 512; j++) {
1146 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1176 startx /= realtexdetail;
1177 starty /= realtexdetail;
1178 endx /= realtexdetail;
1179 endy /= realtexdetail;
1181 int texdetailint = realtexdetail;
1183 if (creature == rabbittype)
1184 for (i = startx; i < endx; i++) {
1185 for (j = starty; j < endy; j++) {
1186 if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
1187 color = Random() % 85 + 170;
1188 where = i * skeleton.skinsize * 3 + j * 3;
1189 if (skeleton.skinText[where + 0] > color / 2)
1190 skeleton.skinText[where + 0] = color / 2;
1191 skeleton.skinText[where + 1] = 0;
1192 skeleton.skinText[where + 2] = 0;
1193 } else if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= 160 + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= 160 - 4) {
1194 color = Random() % 85 + 170;
1195 where = i * skeleton.skinsize * 3 + j * 3;
1196 if (skeleton.skinText[where + 0] > color / 2)
1197 skeleton.skinText[where + 0] = color / 2;
1198 skeleton.skinText[where + 1] = 0;
1199 skeleton.skinText[where + 2] = 0;
1203 if (creature == wolftype)
1204 for (i = startx; i < endx; i++) {
1205 for (j = starty; j < endy; j++) {
1206 if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
1207 color = Random() % 85 + 170;
1208 where = i * skeleton.skinsize * 3 + j * 3;
1209 if (skeleton.skinText[where + 0] > color / 2)
1210 skeleton.skinText[where + 0] = color / 2;
1211 skeleton.skinText[where + 1] = 0;
1212 skeleton.skinText[where + 2] = 0;
1213 } else if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= 160 + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= 160 - 4) {
1214 color = Random() % 85 + 170;
1215 where = i * skeleton.skinsize * 3 + j * 3;
1216 if (skeleton.skinText[where + 0] > color / 2)
1217 skeleton.skinText[where + 0] = color / 2;
1218 skeleton.skinText[where + 1] = 0;
1219 skeleton.skinText[where + 2] = 0;
1223 skeleton.drawmodel.textureptr.bind();
1226 bleedy = (1 + coordsy) * 512;
1227 bleedx = coordsx * 512;
1228 bleedy /= realtexdetail;
1229 bleedx /= realtexdetail;
1234 if (bleedx > skeleton.skinsize - 1)
1235 bleedx = skeleton.skinsize - 1;
1236 if (bleedy > skeleton.skinsize - 1)
1237 bleedy = skeleton.skinsize - 1;
1238 direction = abs(Random() % 2) * 2 - 1;
1243 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1244 deathbleeding += bleeding;
1245 bloodloss += bleeding * 3;
1247 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1248 if (abs(Random() % 2) == 0) {
1249 aitype = gethelptype;
1252 aitype = attacktypecutoff;
1261 * guessing this performs a reversal
1263 void Person::Reverse()
1265 if (!((victim->aitype == playercontrolled || hostiletime > 1 || staggerdelay <= 0) && victim->animTarget != jumpupanim && victim->animTarget != jumpdownanim && (!Tutorial::active || cananger) && hostile))
1268 if (normaldotproduct(victim->facing, victim->coords - coords) > 0 && (victim->id != 0 || difficulty >= 2) && (creature != wolftype || victim->creature == wolftype))
1271 if (animTarget == sweepanim) {
1272 animTarget = sweepreversedanim;
1273 animCurrent = sweepreversedanim;
1274 victim->animCurrent = sweepreversalanim;
1275 victim->animTarget = sweepreversalanim;
1277 if (animTarget == spinkickanim) {
1278 animTarget = spinkickreversedanim;
1279 animCurrent = spinkickreversedanim;
1280 victim->animCurrent = spinkickreversalanim;
1281 victim->animTarget = spinkickreversalanim;
1283 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1284 if (animTarget == rabbittacklinganim) {
1287 victim->frameCurrent = 6;
1288 victim->frameTarget = 7;
1290 animTarget = upunchreversedanim;
1291 animCurrent = upunchreversedanim;
1292 victim->animCurrent = upunchreversalanim;
1293 victim->animTarget = upunchreversalanim;
1295 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1296 if (victim->weaponactive != -1) {
1297 victim->throwtogglekeydown = 1;
1298 XYZ tempVelocity = victim->velocity * .2;
1299 if (tempVelocity.x == 0)
1300 tempVelocity.x = .1;
1301 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1302 victim->num_weapons--;
1303 if (victim->num_weapons) {
1304 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1305 if (victim->weaponstuck == victim->num_weapons)
1306 victim->weaponstuck = 0;
1309 victim->weaponactive = -1;
1310 for (unsigned j = 0; j < Person::players.size(); j++) {
1311 Person::players[j]->wentforweapon = 0;
1315 animTarget = staffhitreversedanim;
1316 animCurrent = staffhitreversedanim;
1317 victim->animCurrent = staffhitreversalanim;
1318 victim->animTarget = staffhitreversalanim;
1320 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1321 if (victim->weaponactive != -1) {
1322 victim->throwtogglekeydown = 1;
1323 XYZ tempVelocity = victim->velocity * .2;
1324 if (tempVelocity.x == 0)
1325 tempVelocity.x = .1;
1326 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1327 victim->num_weapons--;
1328 if (victim->num_weapons) {
1329 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1330 if (victim->weaponstuck == victim->num_weapons)
1331 victim->weaponstuck = 0;
1334 victim->weaponactive = -1;
1335 for (unsigned j = 0; j < Person::players.size(); j++) {
1336 Person::players[j]->wentforweapon = 0;
1339 animTarget = staffspinhitreversedanim;
1340 animCurrent = staffspinhitreversedanim;
1341 victim->animCurrent = staffspinhitreversalanim;
1342 victim->animTarget = staffspinhitreversalanim;
1344 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1345 if (victim->weaponactive != -1) {
1346 victim->throwtogglekeydown = 1;
1347 XYZ tempVelocity = victim->velocity * .2;
1348 if (tempVelocity.x == 0)
1349 tempVelocity.x = .1;
1350 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1351 victim->num_weapons--;
1352 if (victim->num_weapons) {
1353 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1354 if (victim->weaponstuck == victim->num_weapons)
1355 victim->weaponstuck = 0;
1358 victim->weaponactive = -1;
1359 for (unsigned j = 0; j < Person::players.size(); j++) {
1360 Person::players[j]->wentforweapon = 0;
1363 animTarget = swordslashreversedanim;
1364 animCurrent = swordslashreversedanim;
1365 victim->animCurrent = swordslashreversalanim;
1366 victim->animTarget = swordslashreversalanim;
1368 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1369 if (victim->weaponactive != -1) {
1370 victim->throwtogglekeydown = 1;
1371 XYZ tempVelocity = victim->velocity * .2;
1372 if (tempVelocity.x == 0)
1373 tempVelocity.x = .1;
1374 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1375 victim->num_weapons--;
1376 if (victim->num_weapons) {
1377 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1378 if (victim->weaponstuck == victim->num_weapons)
1379 victim->weaponstuck = 0;
1382 victim->weaponactive = -1;
1383 for (unsigned j = 0; j < Person::players.size(); j++) {
1384 Person::players[j]->wentforweapon = 0;
1387 animTarget = knifeslashreversedanim;
1388 animCurrent = knifeslashreversedanim;
1389 victim->animCurrent = knifeslashreversalanim;
1390 victim->animTarget = knifeslashreversalanim;
1392 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1393 victim->targettilt2 = targettilt2;
1394 victim->frameCurrent = frameCurrent;
1395 victim->frameTarget = frameTarget;
1396 victim->target = target;
1397 victim->velocity = 0;
1398 victim->oldcoords = victim->coords;
1399 victim->coords = coords;
1400 victim->targetyaw = targetyaw;
1401 victim->yaw = targetyaw;
1402 victim->victim = this->shared_from_this();
1404 if (animTarget == winduppunchanim) {
1405 animTarget = winduppunchblockedanim;
1406 victim->animTarget = blockhighleftanim;
1407 victim->frameTarget = 1;
1408 victim->target = .5;
1409 victim->victim = this->shared_from_this();
1410 victim->targetyaw = targetyaw + 180;
1412 if (animTarget == wolfslapanim) {
1413 animTarget = winduppunchblockedanim;
1414 victim->animTarget = blockhighleftanim;
1415 victim->frameTarget = 1;
1416 victim->target = .5;
1417 victim->victim = this->shared_from_this();
1418 victim->targetyaw = targetyaw + 180;
1420 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1421 animTarget = swordslashparriedanim;
1422 parriedrecently = .4;
1423 victim->parriedrecently = 0;
1424 victim->animTarget = swordslashparryanim;
1425 victim->frameTarget = 1;
1426 victim->target = .5;
1427 victim->victim = this->shared_from_this();
1428 victim->targetyaw = targetyaw + 180;
1430 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1431 if (victim->weaponactive != -1) {
1432 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1433 if (weapons[victim->weaponids[0]].getType() == staff)
1434 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1435 if (weapons[weaponids[0]].getType() == staff)
1436 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1437 emit_sound_at(swordstaffsound, victim->coords);
1439 emit_sound_at(metalhitsound, victim->coords);
1443 victim->Puff(righthand);
1445 victim->frameTarget = 0;
1446 victim->animTarget = staggerbackhighanim;
1447 victim->targetyaw = targetyaw + 180;
1449 aim = DoRotation(facing, 0, 90, 0) * 21;
1451 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1452 victim->num_weapons--;
1453 if (victim->num_weapons) {
1454 victim->weaponids[0] = victim->weaponids[num_weapons];
1455 if (victim->weaponstuck == victim->num_weapons)
1456 victim->weaponstuck = 0;
1458 victim->weaponactive = -1;
1459 for (unsigned i = 0; i < Person::players.size(); i++) {
1460 Person::players[i]->wentforweapon = 0;
1464 if (abs(Random() % 20) == 0) {
1465 if (weaponactive != -1) {
1466 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1467 if (weapons[victim->weaponids[0]].getType() == staff)
1468 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1469 if (weapons[weaponids[0]].getType() == staff)
1470 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1472 emit_sound_at(swordstaffsound, coords);
1474 emit_sound_at(metalhitsound, coords);
1482 animTarget = staggerbackhighanim;
1483 targetyaw = targetyaw + 180;
1485 aim = DoRotation(facing, 0, 90, 0) * 21;
1487 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1490 weaponids[0] = weaponids[num_weapons];
1491 if (weaponstuck == num_weapons)
1495 for (unsigned i = 0; i < Person::players.size(); i++) {
1496 Person::players[i]->wentforweapon = 0;
1501 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1502 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1503 victim->animTarget = dodgebackanim;
1504 victim->frameTarget = 0;
1508 rotatetarget = coords - victim->coords;
1509 Normalise(&rotatetarget);
1510 victim->targetyaw = -asin(0 - rotatetarget.x);
1511 victim->targetyaw *= 360 / 6.28;
1512 if (rotatetarget.z < 0)
1513 victim->targetyaw = 180 - victim->targetyaw;
1515 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1517 victim->lastattack3 = victim->lastattack2;
1518 victim->lastattack2 = victim->lastattack;
1519 victim->lastattack = victim->animTarget;
1521 victim->animTarget = sweepanim;
1522 victim->frameTarget = 0;
1526 rotatetarget = coords - victim->coords;
1527 Normalise(&rotatetarget);
1528 victim->targetyaw = -asin(0 - rotatetarget.x);
1529 victim->targetyaw *= 360 / 6.28;
1530 if (rotatetarget.z < 0)
1531 victim->targetyaw = 180 - victim->targetyaw;
1533 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1535 victim->lastattack3 = victim->lastattack2;
1536 victim->lastattack2 = victim->lastattack;
1537 victim->lastattack = victim->animTarget;
1542 victim->velocity = 0;
1544 if (aitype != playercontrolled) {
1546 if (escapednum < 2) {
1547 int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
1548 if ((Random() % chances) == 0) {
1554 if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal)
1561 void Person::DoDamage(float howmuch)
1565 damagetaken += howmuch / power;
1567 damagedealt += howmuch / power;
1571 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo)) {
1576 if (!Tutorial::active) {
1577 damage += howmuch / power;
1578 permanentdamage += howmuch / 2 / power;
1579 superpermanentdamage += howmuch / 4 / power;
1582 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1584 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1588 camerashake += howmuch / 100;
1589 if ((howmuch > 50 && damage > damagetolerance / 2)) {
1590 blackout = damage / damagetolerance;
1598 if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile))
1599 aitype = attacktypecutoff;
1600 if (!Tutorial::active && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1601 if (abs(Random() % 2) == 0) {
1602 aitype = gethelptype;
1605 aitype = attacktypecutoff;
1609 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1612 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1613 if (skeleton.free) {
1614 flatvelocity2 = skeleton.joints[i].velocity;
1615 flatfacing2 = skeleton.joints[i].position * scale + coords;
1617 flatvelocity2 = velocity;
1618 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1620 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1621 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1622 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1623 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1624 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1625 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1628 emit_sound_at(splattersound, coords);
1633 if (!dead && creature == wolftype) {
1634 award_bonus(0, Wolfbonus);
1641 if (!Tutorial::active || id == 0) {
1642 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1643 int whichsound = -1;
1645 if (creature == wolftype) {
1646 int i = abs(Random() % 2);
1648 whichsound = snarlsound;
1650 whichsound = snarl2sound;
1652 if (creature == rabbittype) {
1653 int i = abs(Random() % 2);
1655 whichsound = rabbitpainsound;
1656 if (i == 1 && damage > damagetolerance)
1657 whichsound = rabbitpain1sound;
1660 if (whichsound != -1) {
1661 emit_sound_at(whichsound, coords);
1662 addEnvSound(coords);
1670 * calculate/animate head facing direction?
1672 void Person::DoHead()
1674 static XYZ rotatearound;
1676 static float lookspeed = 500;
1678 if (!freeze && !winfreeze) {
1681 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1682 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1684 while (targetheadyaw > 180)
1685 targetheadyaw -= 360;
1686 while (targetheadyaw < -180)
1687 targetheadyaw += 360;
1689 if (targetheadyaw > 160)
1690 targetheadpitch = targetheadpitch * -1;
1691 if (targetheadyaw < -160)
1692 targetheadpitch = targetheadpitch * -1;
1693 if (targetheadyaw > 160)
1694 targetheadyaw = targetheadyaw - 180;
1695 if (targetheadyaw < -160)
1696 targetheadyaw = targetheadyaw + 180;
1698 if (targetheadpitch > 120)
1699 targetheadpitch = 120;
1700 if (targetheadpitch < -120)
1701 targetheadpitch = -120;
1702 if (targetheadyaw > 120)
1703 targetheadyaw = 120;
1704 if (targetheadyaw < -120)
1705 targetheadyaw = -120;
1708 targetheadpitch = 0;
1710 if (targetheadyaw > 80)
1712 if (targetheadyaw < -80)
1713 targetheadyaw = -80;
1714 if (targetheadpitch > 50)
1715 targetheadpitch = 50;
1716 if (targetheadpitch < -50)
1717 targetheadpitch = -50;
1720 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1721 headyaw = targetheadyaw;
1722 else if (headyaw > targetheadyaw) {
1723 headyaw -= multiplier * lookspeed;
1724 } else if (headyaw < targetheadyaw) {
1725 headyaw += multiplier * lookspeed;
1728 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1729 headpitch = targetheadpitch;
1730 else if (headpitch > targetheadpitch) {
1731 headpitch -= multiplier * lookspeed / 2;
1732 } else if (headpitch < targetheadpitch) {
1733 headpitch += multiplier * lookspeed / 2;
1736 rotatearound = jointPos(neck);
1737 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1741 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1742 facing = DoRotation(facing, headpitch * .4, 0, 0);
1743 facing = DoRotation(facing, 0, headyaw * .4, 0);
1746 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1747 facing = DoRotation(facing, headpitch * .8, 0, 0);
1748 facing = DoRotation(facing, 0, headyaw * .8, 0);
1751 if (animTarget == walkanim) {
1752 facing = DoRotation(facing, headpitch * .6, 0, 0);
1753 facing = DoRotation(facing, 0, headyaw * .6, 0);
1756 skeleton.specialforward[0] = facing;
1757 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1758 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
1759 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1760 skeleton.FindRotationMuscle(i, animTarget);
1767 * ragdolls character?
1769 void Person::RagDoll(bool checkcollision)
1774 if (!skeleton.free) {
1777 if (id == 0 && isFlip())
1784 facing = DoRotation(facing, 0, yaw, 0);
1786 skeleton.freetime = 0;
1788 skeleton.longdead = 0;
1791 skeleton.broken = 0;
1792 skeleton.spinny = 1;
1794 skeleton.freefall = 1;
1796 if (!isnormal(velocity.x))
1798 if (!isnormal(velocity.y))
1800 if (!isnormal(velocity.z))
1804 if (!isnormal(coords.x))
1806 if (!isnormal(tilt))
1808 if (!isnormal(tilt2))
1811 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1812 skeleton.joints[i].delay = 0;
1813 skeleton.joints[i].locked = 0;
1814 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1815 if (!isnormal(skeleton.joints[i].position.x))
1816 skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1817 if (!isnormal(skeleton.joints[i].position.x))
1818 skeleton.joints[i].position = coords;
1819 skeleton.joints[i].position.y += .1;
1820 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1821 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1824 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1825 skeleton.joints[i].velocity = 0;
1826 skeleton.joints[i].velchange = 0;
1828 skeleton.DoConstraints(&coords, &scale);
1829 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
1830 skeleton.DoConstraints(&coords, &scale);
1831 skeleton.DoConstraints(&coords, &scale);
1832 skeleton.DoConstraints(&coords, &scale);
1833 skeleton.DoConstraints(&coords, &scale);
1836 speed = targetFrame().speed * 2;
1837 if (currentFrame().speed > targetFrame().speed) {
1838 speed = currentFrame().speed * 2;
1841 speed = transspeed * 2;
1845 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1846 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height)
1847 skeleton.joints[i].velocity = velocity / scale + facing * 5 + DoRotation(DoRotation(DoRotation((targetFrame().joints[i].position - currentFrame().joints[i].position) * speed, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1849 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1850 change.x = (float)(Random() % 100) / 100;
1851 change.y = (float)(Random() % 100) / 100;
1852 change.z = (float)(Random() % 100) / 100;
1853 skeleton.joints[i].velocity += change;
1854 skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change;
1856 change.x = (float)(Random() % 100) / 100;
1857 change.y = (float)(Random() % 100) / 100;
1858 change.z = (float)(Random() % 100) / 100;
1859 skeleton.joints[i].velchange += change;
1860 skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change;
1863 if (checkcollision) {
1866 if (!skeleton.joints.empty()) {
1869 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1870 average += skeleton.joints[j].position;
1872 average /= skeleton.joints.size();
1873 coords += average * scale;
1874 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1875 skeleton.joints[j].position -= average;
1879 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1880 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1881 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
1882 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1885 if (SphereCheck(&lowpoint, 3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
1886 coords.x = lowpoint.x;
1887 coords.z = lowpoint.z;
1896 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1897 velocity += skeleton.joints[i].velocity * scale;
1899 velocity /= skeleton.joints.size();
1902 if (Random() % 2 == 0) {
1903 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1904 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1905 weapons[weaponids[0]].velocity.x += .01;
1908 weaponids[0] = weaponids[num_weapons];
1909 if (weaponstuck == num_weapons)
1913 for (unsigned i = 0; i < Person::players.size(); i++) {
1914 Person::players[i]->wentforweapon = 0;
1919 animTarget = bounceidleanim;
1920 animCurrent = bounceidleanim;
1928 void Person::FootLand(bodypart whichfoot, float opacity)
1930 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
1931 cerr << "FootLand called on wrong bodypart" << endl;
1934 static XYZ terrainlight;
1935 static XYZ footvel, footpoint;
1936 if (opacity >= 1 || skiddelay <= 0) {
1939 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1940 if (distsq(&footpoint, &viewer))
1941 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1942 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1943 footvel = velocity / 5;
1946 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1947 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1948 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1949 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1950 if (environment == snowyenvironment) {
1951 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1953 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1955 } else if (environment == grassyenvironment) {
1956 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1957 } else if (environment == desertenvironment) {
1958 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1960 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1964 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
1965 footvel = velocity / 5;
1968 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1969 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1970 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1977 * make a puff effect at a body part (dust effect?)
1979 void Person::Puff(int whichlabel)
1981 static XYZ footvel, footpoint;
1984 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1985 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1989 * I think I added this in an attempt to clean up code
1991 void Person::setTargetAnimation(int animation)
1993 animTarget = animation;
2002 void Person::DoAnimations()
2004 if (!skeleton.free) {
2005 static float oldtarget;
2007 if (isIdle() && animCurrent != getIdle())
2008 normalsupdatedelay = 0;
2010 if (animTarget == tempanim || animCurrent == tempanim) {
2011 Animation::animations[tempanim] = tempanimation;
2013 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
2019 vel[0] = velocity.x;
2020 vel[1] = velocity.y;
2021 vel[2] = velocity.z;
2024 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
2025 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
2027 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
2029 if (!crouchkeydown && velocity.y >= -15)
2032 if ((animCurrent == jumpupanim || animTarget == jumpdownanim) /*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
2037 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
2039 if (normaldotproduct(targfacing, velocity) >= -.3)
2040 animTarget = flipanim;
2042 animTarget = backflipanim;
2043 crouchtogglekeydown = 1;
2051 if (Animation::animations[animTarget].attack != reversed)
2053 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
2054 crouchtogglekeydown = 0;
2055 if (aitype == playercontrolled)
2058 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
2061 crouchtogglekeydown = 1;
2064 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
2066 normalsupdatedelay = 0;
2070 if (animTarget == rollanim && frameTarget == 3 && onfire) {
2072 emit_sound_at(fireendsound, coords);
2073 pause_sound(stream_firesound);
2077 if (animTarget == rabbittacklinganim && frameTarget == 1) {
2078 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
2080 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
2081 if (normaldotproduct(victim->facing, facing) > 0)
2082 victim->animTarget = rabbittackledbackanim;
2084 victim->animTarget = rabbittackledfrontanim;
2085 victim->frameTarget = 2;
2088 victim->targetyaw = yaw;
2089 if (victim->aitype == gethelptype)
2090 victim->DoDamage(victim->damagetolerance - victim->damage);
2091 //victim->DoDamage(30);
2092 if (creature == wolftype) {
2094 emit_sound_at(clawslicesound, victim->coords);
2096 victim->DoBloodBig(1 / victim->armorhead, 210);
2098 award_bonus(id, TackleBonus,
2099 victim->aitype == gethelptype ? 50 : 0);
2103 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2104 if (weapons[weaponids[0]].getType() == knife) {
2105 if (weaponactive == -1)
2107 else if (weaponactive == 0)
2110 if (weaponactive == -1) {
2111 emit_sound_at(knifesheathesound, coords);
2113 if (weaponactive != -1) {
2114 emit_sound_at(knifedrawsound, coords, 128);
2117 drawtogglekeydown = 1;
2120 if (!Tutorial::active || id == 0)
2121 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2122 int whichsound = -1;
2124 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2125 if (targetFrame().label == 1)
2126 whichsound = footstepsound;
2128 whichsound = footstepsound2;
2129 if (targetFrame().label == 1)
2130 FootLand(leftfoot, 1);
2131 if (targetFrame().label == 2)
2132 FootLand(rightfoot, 1);
2133 if (targetFrame().label == 3 && isRun()) {
2134 FootLand(rightfoot, 1);
2135 FootLand(leftfoot, 1);
2138 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2139 if (targetFrame().label == 1)
2140 whichsound = footstepsound3;
2142 whichsound = footstepsound4;
2146 if (targetFrame().label == 1)
2147 whichsound = footstepsound3;
2149 whichsound = footstepsound4;
2151 if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2152 if (Animation::animations[animTarget].attack != neutral) {
2153 unsigned r = abs(Random() % 3);
2155 whichsound = lowwhooshsound;
2157 whichsound = midwhooshsound;
2159 whichsound = highwhooshsound;
2161 if (Animation::animations[animTarget].attack == neutral) {
2162 whichsound = movewhooshsound;
2164 } else if (targetFrame().label == 4) {
2165 whichsound = knifeswishsound;
2167 if (targetFrame().label == 8 && !Tutorial::active) {
2168 whichsound = landsound2;
2171 if (whichsound != -1) {
2172 emit_sound_at(whichsound, coords, 256.);
2175 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2176 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2177 addEnvSound(coords, 15);
2179 addEnvSound(coords, 6);
2184 if (targetFrame().label == 3) {
2186 emit_sound_at(whichsound, coords, 128.);
2192 if (!Tutorial::active || id == 0)
2193 if (speechdelay <= 0)
2194 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
2195 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2196 int whichsound = -1;
2197 if (targetFrame().label == 4 && aitype != playercontrolled) {
2198 if (Animation::animations[animTarget].attack != neutral) {
2199 unsigned r = abs(Random() % 4);
2200 if (creature == rabbittype) {
2202 whichsound = rabbitattacksound;
2204 whichsound = rabbitattack2sound;
2206 whichsound = rabbitattack3sound;
2208 whichsound = rabbitattack4sound;
2210 if (creature == wolftype) {
2212 whichsound = barksound;
2214 whichsound = bark2sound;
2216 whichsound = bark3sound;
2218 whichsound = barkgrowlsound;
2224 if (whichsound != -1) {
2225 emit_sound_at(whichsound, coords);
2229 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2230 FootLand(leftfoot, 1);
2231 FootLand(rightfoot, 1);
2235 currentoffset = targetoffset;
2236 frameTarget = frameCurrent;
2237 animCurrent = animTarget;
2240 if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2241 for (unsigned i = 0; i < weapons.size(); i++) {
2242 if (weapons[i].owner == -1)
2243 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2244 if (distsq(&coords, &weapons[i].position) >= 1) {
2245 if (weapons[i].getType() != staff) {
2246 emit_sound_at(knifedrawsound, coords, 128.);
2255 if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2256 for (unsigned i = 0; i < weapons.size(); i++) {
2257 bool willwork = true;
2258 if (weapons[i].owner != -1)
2259 if (Person::players[weapons[i].owner]->weaponstuck != -1)
2260 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2261 if (Person::players[weapons[i].owner]->num_weapons > 1)
2263 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2264 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2265 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2266 bool fleshstuck = false;
2267 if (weapons[i].owner != -1)
2268 if (victim->weaponstuck != -1) {
2269 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2274 emit_sound_at(fleshstabremovesound, coords, 128.);
2276 if (weapons[i].getType() != staff) {
2277 emit_sound_at(knifedrawsound, coords, 128.);
2280 if (weapons[i].owner != -1) {
2281 victim = Person::players[weapons[i].owner];
2282 if (victim->num_weapons == 1)
2283 victim->num_weapons = 0;
2285 victim->num_weapons = 1;
2287 //victim->weaponactive=-1;
2288 victim->skeleton.longdead = 0;
2289 victim->skeleton.free = 1;
2290 victim->skeleton.broken = 0;
2292 for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) {
2293 victim->skeleton.joints[j].velchange = 0;
2294 victim->skeleton.joints[j].locked = 0;
2300 Normalise(&relative);
2301 XYZ footvel, footpoint;
2303 footpoint = weapons[i].position;
2304 if (victim->weaponstuck != -1) {
2305 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2307 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2308 weapons[i].bloody = 2;
2309 weapons[i].blooddrip = 5;
2310 victim->weaponstuck = -1;
2313 if (victim->num_weapons > 0) {
2314 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2315 victim->weaponstuck = 0;
2316 if (victim->weaponids[0] == int(i))
2317 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2320 victim->jointVel(abdomen) += relative * 6;
2321 victim->jointVel(neck) += relative * 6;
2322 victim->jointVel(rightshoulder) += relative * 6;
2323 victim->jointVel(leftshoulder) += relative * 6;
2331 if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2332 if (weaponactive == -1)
2334 else if (weaponactive == 0) {
2336 if (num_weapons == 2) {
2338 buffer = weaponids[0];
2339 weaponids[0] = weaponids[1];
2340 weaponids[1] = buffer;
2343 if (weaponactive == -1) {
2344 emit_sound_at(knifesheathesound, coords, 128.);
2346 if (weaponactive != -1) {
2347 emit_sound_at(knifedrawsound, coords, 128.);
2351 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2352 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2353 Normalise(&rotatetarget);
2354 targetyaw = -asin(0 - rotatetarget.x);
2355 targetyaw *= 360 / 6.28;
2356 if (rotatetarget.z < 0)
2357 targetyaw = 180 - targetyaw;
2359 if (animTarget == walljumprightkickanim)
2361 if (animTarget == walljumpleftkickanim)
2367 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2370 if (distsq(&victim->coords, &/*Person::players[i]->*/ coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2375 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2376 animTarget = rabbittackleanim;
2378 emit_sound_at(jumpsound, coords);
2386 targetloc = velocity;
2387 Normalise(&targetloc);
2388 targetloc += coords;
2389 for (unsigned i = 0; i < Person::players.size(); i++) {
2391 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2392 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2396 if (closestid != -1)
2397 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2399 victim = Person::players[closestid];
2400 coords = victim->coords;
2401 animCurrent = rabbittacklinganim;
2402 animTarget = rabbittacklinganim;
2406 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2407 rotatetarget = coords - victim->coords;
2408 Normalise(&rotatetarget);
2409 targetyaw = -asin(0 - rotatetarget.x);
2410 targetyaw *= 360 / 6.28;
2411 if (rotatetarget.z < 0)
2412 targetyaw = 180 - targetyaw;
2414 if (animTarget != rabbitrunninganim) {
2415 emit_sound_at(jumpsound, coords, 128.);
2421 float damagemult = 1 * power;
2422 if (creature == wolftype)
2423 damagemult = 2.5 * power;
2425 damagemult /= victim->damagetolerance / 200;
2427 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)) {
2428 if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2429 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2433 if (Random() % 2 || creature == wolftype) {
2436 if (creature == wolftype)
2439 if (!Tutorial::active) {
2440 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2442 if (creature == wolftype) {
2443 emit_sound_at(clawslicesound, victim->coords, 128.);
2445 victim->DoBloodBig(2 / victim->armorhead, 175);
2449 relative = victim->coords - coords;
2451 Normalise(&relative);
2452 relative = DoRotation(relative, 0, -90, 0);
2453 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2454 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2456 victim->jointVel(head) += relative * damagemult * 200;
2458 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2464 if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2465 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2469 if (Random() % 2 || creature == wolftype) {
2471 if (creature == wolftype)
2474 emit_sound_at(whooshhitsound, victim->coords);
2475 if (creature == wolftype) {
2476 emit_sound_at(clawslicesound, victim->coords, 128.);
2478 victim->DoBloodBig(2, 175);
2482 relative = victim->coords - coords;
2484 Normalise(&relative);
2486 Normalise(&relative);
2487 relative = DoRotation(relative, 0, 90, 0);
2488 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2489 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2491 victim->jointVel(head) += relative * damagemult * 100;
2493 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2497 if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2498 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2504 if (!Tutorial::active) {
2505 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2507 if (creature == wolftype) {
2508 emit_sound_at(clawslicesound, victim->coords, 128.);
2510 victim->DoBloodBig(2 / victim->armorhead, 175);
2516 Normalise(&relative);
2517 relative = DoRotation(relative, 0, -90, 0);
2518 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2519 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2521 victim->jointVel(head) += relative * damagemult * 200;
2523 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2525 if (victim->damage > victim->damagetolerance)
2526 award_bonus(id, style);
2532 if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2533 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2539 if (!Tutorial::active) {
2540 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2542 if (creature == wolftype) {
2543 emit_sound_at(clawslicesound, victim->coords, 128.);
2545 victim->DoBloodBig(2 / victim->armorhead, 175);
2551 Normalise(&relative);
2552 relative = DoRotation(relative, 0, 90, 0);
2553 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2554 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2556 victim->jointVel(head) += relative * damagemult * 200;
2558 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2560 if (victim->damage > victim->damagetolerance)
2561 award_bonus(id, style);
2567 if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2568 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2576 emit_sound_at(whooshhitsound, victim->coords);
2579 relative = victim->coords - coords;
2581 Normalise(&relative);
2582 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2583 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2585 victim->jointVel(head) += relative * damagemult * 100;
2587 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2591 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
2592 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2596 emit_sound_at(whooshhitsound, victim->coords, 128.);
2598 victim->skeleton.longdead = 0;
2599 victim->skeleton.free = 1;
2600 victim->skeleton.broken = 0;
2601 victim->skeleton.spinny = 1;
2603 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2604 victim->skeleton.joints[i].velchange = 0;
2605 victim->skeleton.joints[i].delay = 0;
2606 victim->skeleton.joints[i].locked = 0;
2607 //victim->skeleton.joints[i].velocity=0;
2613 Normalise(&relative);
2614 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2615 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2616 victim->skeleton.joints[i].position.y += relative.y * .3;
2617 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2618 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2620 victim->Puff(abdomen);
2621 victim->jointVel(abdomen).y = relative.y * 400;
2625 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2626 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2630 if (!Tutorial::active) {
2631 emit_sound_at(heavyimpactsound, coords, 128.);
2634 relative = victim->coords - coords;
2636 Normalise(&relative);
2637 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2638 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2640 victim->Puff(abdomen);
2641 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2645 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2646 victim->jointVel(abdomen) += relative * damagemult * 300;
2650 if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
2651 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2655 if (!Tutorial::active) {
2656 emit_sound_at(thudsound, coords);
2659 victim->skeleton.longdead = 0;
2660 victim->skeleton.free = 1;
2661 victim->skeleton.broken = 0;
2662 victim->skeleton.spinny = 1;
2664 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2665 victim->skeleton.joints[i].velchange = 0;
2666 //victim->skeleton.joints[i].delay=0;
2667 victim->skeleton.joints[i].locked = 0;
2670 relative = victim->coords - coords;
2671 Normalise(&relative);
2673 Normalise(&relative);
2674 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2675 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2680 victim->Puff(abdomen);
2681 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2682 victim->jointVel(abdomen) += relative * damagemult * 200;
2689 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2692 if (!victim->skeleton.free)
2696 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2697 emit_sound_at(knifesheathesound, coords, 128.);
2700 if (victim && hasvictim) {
2701 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2703 XYZ where, startpoint, endpoint, movepoint, colpoint;
2704 float rotationpoint;
2706 if (weapons[weaponids[weaponactive]].getType() == knife) {
2707 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2708 where -= victim->coords;
2709 if (!victim->skeleton.free)
2710 where = DoRotation(where, 0, -victim->yaw, 0);
2713 startpoint.y += 100;
2717 if (weapons[weaponids[weaponactive]].getType() == sword) {
2718 where = weapons[weaponids[weaponactive]].position;
2719 where -= victim->coords;
2720 if (!victim->skeleton.free)
2721 where = DoRotation(where, 0, -victim->yaw, 0);
2723 where = weapons[weaponids[weaponactive]].tippoint;
2724 where -= victim->coords;
2725 if (!victim->skeleton.free)
2726 where = DoRotation(where, 0, -victim->yaw, 0);
2729 if (weapons[weaponids[weaponactive]].getType() == staff) {
2730 where = weapons[weaponids[weaponactive]].position;
2731 where -= victim->coords;
2732 if (!victim->skeleton.free)
2733 where = DoRotation(where, 0, -victim->yaw, 0);
2735 where = weapons[weaponids[weaponactive]].tippoint;
2736 where -= victim->coords;
2737 if (!victim->skeleton.free)
2738 where = DoRotation(where, 0, -victim->yaw, 0);
2743 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2745 if (whichtri != -1) {
2746 if (victim->dead != 2) {
2747 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2749 award_bonus(id, FinishedBonus);
2752 weapons[weaponids[weaponactive]].bloody = 2;
2754 victim->skeleton.longdead = 0;
2755 victim->skeleton.free = 1;
2756 victim->skeleton.broken = 0;
2758 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2759 victim->skeleton.joints[i].velchange = 0;
2760 victim->skeleton.joints[i].locked = 0;
2761 //victim->skeleton.joints[i].velocity=0;
2763 emit_sound_at(fleshstabsound, coords, 128);
2765 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2766 weapons[weaponids[weaponactive]].blooddrip += 5;
2767 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2769 if (whichtri == -1) {
2771 emit_sound_at(knifesheathesound, coords, 128.);
2777 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
2779 emit_sound_at(knifedrawsound, coords, 128);
2782 if (victim && hasvictim) {
2783 XYZ footvel, footpoint;
2785 emit_sound_at(fleshstabremovesound, coords, 128.);
2788 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2790 if (weapons[weaponids[weaponactive]].getType() == sword) {
2791 XYZ where, startpoint, endpoint, movepoint;
2792 float rotationpoint;
2795 where = weapons[weaponids[weaponactive]].position;
2796 where -= victim->coords;
2797 if (!victim->skeleton.free)
2798 where = DoRotation(where, 0, -victim->yaw, 0);
2800 where = weapons[weaponids[weaponactive]].tippoint;
2801 where -= victim->coords;
2802 if (!victim->skeleton.free)
2803 where = DoRotation(where, 0, -victim->yaw, 0);
2808 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2809 footpoint += victim->coords;
2811 if (whichtri == -1) {
2812 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2815 if (weapons[weaponids[weaponactive]].getType() == staff) {
2816 XYZ where, startpoint, endpoint, movepoint;
2817 float rotationpoint;
2820 where = weapons[weaponids[weaponactive]].position;
2821 where -= victim->coords;
2822 if (!victim->skeleton.free)
2823 where = DoRotation(where, 0, -victim->yaw, 0);
2825 where = weapons[weaponids[weaponactive]].tippoint;
2826 where -= victim->coords;
2827 if (!victim->skeleton.free)
2828 where = DoRotation(where, 0, -victim->yaw, 0);
2833 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2834 footpoint += victim->coords;
2836 if (whichtri == -1) {
2837 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2840 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2842 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2843 victim->skeleton.longdead = 0;
2844 victim->skeleton.free = 1;
2845 victim->skeleton.broken = 0;
2847 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2848 victim->skeleton.joints[i].velchange = 0;
2849 victim->skeleton.joints[i].locked = 0;
2850 //victim->skeleton.joints[i].velocity=0;
2856 Normalise(&relative);
2857 //victim->Puff(abdomen);
2859 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2861 if (victim->bloodloss < victim->damagetolerance) {
2862 victim->bloodloss += 1000;
2866 victim->jointVel(abdomen) += relative * damagemult * 20;
2870 if (!hasvictim && onterrain) {
2871 weapons[weaponids[weaponactive]].bloody = 0;
2872 weapons[weaponids[weaponactive]].blooddrip = 0;
2876 if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2877 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2885 if (!Tutorial::active) {
2886 emit_sound_at(heavyimpactsound, victim->coords, 128);
2891 relative = victim->coords - coords;
2893 Normalise(&relative);
2894 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2895 victim->skeleton.joints[i].velocity = relative * 30;
2897 victim->jointVel(head) += relative * damagemult * 150;
2899 victim->frameTarget = 0;
2900 victim->animTarget = staggerbackhardanim;
2901 victim->targetyaw = targetyaw + 180;
2903 victim->stunned = 1;
2906 victim->Puff(abdomen);
2907 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2913 if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2914 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2918 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
2919 if (!Tutorial::active) {
2920 emit_sound_at(thudsound, victim->coords);
2922 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
2923 if (!Tutorial::active) {
2924 emit_sound_at(whooshhitsound, victim->coords);
2927 if (!Tutorial::active) {
2928 emit_sound_at(heavyimpactsound, victim->coords);
2932 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight)
2935 relative = victim->coords - coords;
2937 Normalise(&relative);
2939 Normalise(&relative);
2940 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2941 victim->skeleton.joints[i].velocity = relative * 5;
2943 victim->jointVel(abdomen) += relative * damagemult * 400;
2945 victim->frameTarget = 0;
2946 victim->animTarget = staggerbackhardanim;
2947 victim->targetyaw = targetyaw + 180;
2949 victim->stunned = 1;
2951 victim->Puff(abdomen);
2952 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2958 if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2959 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2960 if (victim->id == 0)
2962 emit_sound_at(landsound2, victim->coords);
2968 if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2969 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2970 if (victim->id == 0)
2973 if (weaponactive != -1) {
2974 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2975 if (weapons[victim->weaponids[0]].getType() == staff)
2976 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2977 if (weapons[weaponids[0]].getType() == staff)
2978 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2980 emit_sound_at(swordstaffsound, victim->coords);
2982 emit_sound_at(metalhitsound, victim->coords);
2990 if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2991 if (weaponactive != -1) {
2994 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);
2996 weapons[weaponids[0]].thrown(aim * 50);
2999 weaponids[0] = weaponids[num_weapons];
3005 if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3007 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 && /*Animation::animations[victim->animTarget].height!=lowheight&&*/ victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
3009 if (!Tutorial::active) {
3010 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
3013 award_bonus(id, Slicebonus);
3014 if (!Tutorial::active) {
3015 emit_sound_at(knifeslicesound, victim->coords);
3017 //victim->jointVel(abdomen)+=relative*damagemult*200;
3018 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
3019 if (victim->id != 0 || difficulty == 2) {
3020 victim->frameTarget = 0;
3021 victim->animTarget = staggerbackhardanim;
3022 victim->targetyaw = targetyaw + 180;
3026 victim->lowreversaldelay = 0;
3027 victim->highreversaldelay = 0;
3028 if (aitype != playercontrolled)
3029 weaponmissdelay = .6;
3031 if (!Tutorial::active) {
3032 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3033 weapons[weaponids[weaponactive]].bloody = 1;
3035 weapons[weaponids[weaponactive]].blooddrip += 3;
3038 XYZ footvel, footpoint;
3040 if (skeleton.free) {
3041 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3043 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3045 if (Tutorial::active) {
3046 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
3049 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
3051 footvel = DoRotation(facing, 0, 90, 0) * .8;
3052 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3053 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3054 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3055 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3057 victim->DoDamage(damagemult * 0);
3060 if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3061 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
3062 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
3063 award_bonus(id, Slashbonus);
3065 if (!Tutorial::active) {
3066 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
3067 victim->DoBloodBig(2 / victim->armorhigh, 190);
3069 victim->DoBloodBig(2 / victim->armorhigh, 185);
3070 victim->deathbleeding = 1;
3071 emit_sound_at(swordslicesound, victim->coords);
3072 victim->frameTarget = 0;
3073 victim->animTarget = staggerbackhardanim;
3074 victim->targetyaw = targetyaw + 180;
3076 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3077 weapons[weaponids[weaponactive]].bloody = 1;
3079 weapons[weaponids[weaponactive]].blooddrip += 3;
3081 float bloodlossamount;
3082 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
3083 victim->bloodloss += bloodlossamount / victim->armorhigh;
3084 victim->DoDamage(damagemult * 0);
3086 XYZ footvel, footpoint;
3088 if (skeleton.free) {
3089 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3091 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3094 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3096 footvel = DoRotation(facing, 0, 90, 0) * .8;
3098 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3099 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3100 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3101 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3104 if (victim->weaponactive != -1) {
3105 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3106 if (weapons[victim->weaponids[0]].getType() == staff)
3107 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3108 if (weapons[weaponids[0]].getType() == staff)
3109 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3111 emit_sound_at(swordstaffsound, victim->coords);
3113 emit_sound_at(metalhitsound, victim->coords);
3118 victim->Puff(righthand);
3120 victim->frameTarget = 0;
3121 victim->animTarget = staggerbackhighanim;
3122 victim->targetyaw = targetyaw + 180;
3124 aim = DoRotation(facing, 0, 90, 0) * 21;
3126 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3127 victim->num_weapons--;
3128 if (victim->num_weapons) {
3129 victim->weaponids[0] = victim->weaponids[num_weapons];
3130 if (victim->weaponstuck == victim->num_weapons)
3131 victim->weaponstuck = 0;
3133 victim->weaponactive = -1;
3134 for (unsigned i = 0; i < Person::players.size(); i++) {
3135 Person::players[i]->wentforweapon = 0;
3141 if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3142 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3143 if (!Tutorial::active) {
3144 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3148 if (Random() % 2 || creature == wolftype) {
3151 emit_sound_at(staffheadsound, victim->coords);
3155 relative = victim->coords - coords;
3157 Normalise(&relative);
3158 relative = DoRotation(relative, 0, 90, 0);
3160 Normalise(&relative);
3161 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3162 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3164 victim->jointVel(head) += relative * damagemult * 230;
3165 victim->jointVel(neck) += relative * damagemult * 230;
3167 if (!Tutorial::active) {
3168 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3170 award_bonus(id, solidhit, 30);
3175 if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3176 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3177 if (!Tutorial::active) {
3178 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3182 if (Random() % 2 || creature == wolftype) {
3185 emit_sound_at(staffheadsound, victim->coords);
3189 relative = victim->coords - coords;
3191 Normalise(&relative);
3192 relative = DoRotation(relative, 0, -90, 0);
3193 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3194 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3196 victim->jointVel(head) += relative * damagemult * 220;
3197 victim->jointVel(neck) += relative * damagemult * 220;
3199 if (!Tutorial::active) {
3200 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3202 award_bonus(id, solidhit, 60);
3207 if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3208 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3210 if (!Tutorial::active) {
3212 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3215 if (Random() % 2 || creature == wolftype) {
3218 emit_sound_at(staffbodysound, victim->coords);
3220 victim->skeleton.longdead = 0;
3221 victim->skeleton.free = 1;
3222 victim->skeleton.broken = 0;
3224 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3225 victim->skeleton.joints[i].velchange = 0;
3226 victim->skeleton.joints[i].locked = 0;
3227 //victim->skeleton.joints[i].velocity=0;
3234 Normalise(&relative);
3235 if (!victim->dead) {
3236 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3237 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3239 victim->jointVel(abdomen) += relative * damagemult * 40;
3242 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3243 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3246 victim->Puff(abdomen);
3247 if (!Tutorial::active) {
3248 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3250 if (!victim->dead) {
3251 award_bonus(id, solidhit, 40);
3257 if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3258 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3263 relative = victim->coords - coords;
3265 Normalise(&relative);
3269 if (Animation::animations[victim->animTarget].height == lowheight) {
3275 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3276 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3278 victim->jointVel(head) += relative * damagemult * 200;
3279 if (!Tutorial::active) {
3280 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3283 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3284 if (victim->howactive == typesleeping)
3285 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3286 if (creature == wolftype) {
3287 emit_sound_at(clawslicesound, victim->coords, 128.);
3289 victim->DoBloodBig(2 / victim->armorhead, 175);
3292 if (victim->damage >= victim->damagetolerance)
3294 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3295 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3297 victim->jointVel(abdomen) += relative * damagemult * 200;
3298 victim->frameTarget = 0;
3299 victim->animTarget = staggerbackhighanim;
3300 victim->targetyaw = targetyaw + 180;
3302 if (!Tutorial::active) {
3303 emit_sound_at(landsound2, victim->coords, 128.);
3305 victim->Puff(abdomen);
3306 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3307 if (creature == wolftype) {
3308 emit_sound_at(clawslicesound, victim->coords, 128.);
3310 victim->DoBloodBig(2 / victim->armorhigh, 170);
3316 if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3317 if ((victim->animTarget != jumpupanim) &&
3318 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3319 (victim != this->shared_from_this())) {
3323 if (!Tutorial::active) {
3324 emit_sound_at(landsound2, victim->coords, 128.);
3327 relative = victim->coords - coords;
3329 Normalise(&relative);
3331 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3334 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3335 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3337 relative = DoRotation(relative, 0, -90, 0);
3339 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3340 if (victim->skeleton.joints[i].label == leftfoot || victim->skeleton.joints[i].label == rightfoot || victim->skeleton.joints[i].label == leftankle || victim->skeleton.joints[i].label == rightankle)
3341 victim->skeleton.joints[i].velocity = relative * 80;
3343 victim->Puff(rightankle);
3344 victim->Puff(leftankle);
3345 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3347 if (victim->damage >= victim->damagetolerance)
3349 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3350 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3352 relative = DoRotation(relative, 0, -90, 0);
3353 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3354 if (victim->skeleton.joints[i].label == leftfoot || victim->skeleton.joints[i].label == rightfoot || victim->skeleton.joints[i].label == leftankle || victim->skeleton.joints[i].label == rightankle)
3355 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3357 victim->jointVel(abdomen) += relative * damagemult * 200;
3358 victim->frameTarget = 0;
3359 victim->animTarget = staggerbackhighanim;
3360 victim->targetyaw = targetyaw + 180;
3362 if (!Tutorial::active) {
3363 emit_sound_at(landsound2, victim->coords, 128.);
3365 victim->Puff(abdomen);
3366 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3373 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3374 if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3382 if (!Tutorial::active) {
3383 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3385 if (creature == wolftype) {
3386 emit_sound_at(clawslicesound, victim->coords, 128);
3388 victim->DoBloodBig(2 / victim->armorhigh, 170);
3392 relative = victim->coords - oldcoords;
3394 Normalise(&relative);
3395 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3396 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3398 victim->jointVel(abdomen) += relative * damagemult * 200;
3399 victim->Puff(abdomen);
3400 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3402 award_bonus(id, Reversal);
3405 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3406 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3407 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3408 takeWeapon(victim->weaponids[victim->weaponactive]);
3409 victim->num_weapons--;
3410 if (victim->num_weapons > 0) {
3411 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3413 victim->weaponactive = -1;
3418 if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3426 emit_sound_at(whooshhitsound, victim->coords, 128.);
3429 relative = victim->coords - oldcoords;
3431 Normalise(&relative);
3432 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3433 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3435 victim->jointVel(abdomen) += relative * damagemult * 200;
3437 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3440 if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3449 award_bonus(id, staffreversebonus);
3451 if (!Tutorial::active) {
3452 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3455 award_bonus(id, staffreversebonus); // Huh, again?
3458 relative = victim->coords - oldcoords;
3460 Normalise(&relative);
3461 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3462 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3464 victim->jointVel(abdomen) += relative * damagemult * 200;
3466 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3469 if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3475 Normalise(&relative);
3477 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3478 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3480 victim->jointVel(lefthand) *= .1;
3481 victim->jointVel(leftwrist) *= .2;
3482 victim->jointVel(leftelbow) *= .5;
3483 victim->jointVel(leftshoulder) *= .7;
3484 victim->jointVel(righthand) *= .1;
3485 victim->jointVel(rightwrist) *= .2;
3486 victim->jointVel(rightelbow) *= .5;
3487 victim->jointVel(rightshoulder) *= .7;
3489 victim->Puff(abdomen);
3490 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3492 award_bonus(id, Reversal);
3496 if (weaponactive != -1 || creature == wolftype)
3498 if (creature == rabbittype && weaponactive != -1)
3499 if (weapons[weaponids[0]].getType() == staff)
3502 if (weaponactive != -1) {
3503 victim->DoBloodBig(2 / victim->armorhigh, 225);
3504 emit_sound_at(knifeslicesound, victim->coords);
3505 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3506 weapons[weaponids[weaponactive]].bloody = 1;
3507 weapons[weaponids[weaponactive]].blooddrip += 3;
3509 if (weaponactive == -1 && creature == wolftype) {
3510 emit_sound_at(clawslicesound, victim->coords, 128.);
3512 victim->DoBloodBig(2 / victim->armorhigh, 175);
3517 if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3523 Normalise(&relative);
3525 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3526 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3528 victim->jointVel(lefthand) *= .1 - 1;
3529 victim->jointVel(leftwrist) *= .2 - 1;
3530 victim->jointVel(leftelbow) *= .5 - 1;
3531 victim->jointVel(leftshoulder) *= .7 - 1;
3532 victim->jointVel(righthand) *= .1 - 1;
3533 victim->jointVel(rightwrist) *= .2 - 1;
3534 victim->jointVel(rightelbow) *= .5 - 1;
3535 victim->jointVel(rightshoulder) *= .7 - 1;
3537 award_bonus(id, swordreversebonus);
3540 if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3548 if (!Tutorial::active) {
3549 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3553 relative = victim->coords - oldcoords;
3555 Normalise(&relative);
3556 relative = DoRotation(relative, 0, -90, 0);
3557 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3558 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3560 victim->jointVel(abdomen) += relative * damagemult * 200;
3561 victim->Puff(abdomen);
3562 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3564 award_bonus(id, Reversal);
3567 if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3570 victim->skeleton.spinny = 0;
3572 relative = facing * -1;
3574 Normalise(&relative);
3575 if (victim->id == 0)
3577 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3578 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3580 victim->damage = victim->damagetolerance;
3581 victim->permanentdamage = victim->damagetolerance - 1;
3584 if (weaponactive != -1 || creature == wolftype)
3586 if (creature == rabbittype && weaponactive != -1)
3587 if (weapons[weaponids[0]].getType() == staff)
3590 if (weaponactive != -1) {
3591 victim->DoBloodBig(200, 225);
3592 emit_sound_at(knifeslicesound, victim->coords);
3594 weapons[weaponids[weaponactive]].bloody = 2;
3595 weapons[weaponids[weaponactive]].blooddrip += 5;
3598 if (creature == wolftype && weaponactive == -1) {
3599 emit_sound_at(clawslicesound, victim->coords, 128.);
3601 victim->DoBloodBig(2, 175);
3604 award_bonus(id, spinecrusher);
3607 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3608 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3610 if (animTarget == knifefollowanim)
3611 victim->DoBloodBig(200, 210);
3612 if (animTarget == knifesneakattackanim) {
3613 XYZ footvel, footpoint;
3615 footpoint = weapons[weaponids[0]].tippoint;
3617 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3618 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3619 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3620 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3621 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3622 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3623 victim->DoBloodBig(200, 195);
3624 award_bonus(id, tracheotomy);
3626 if (animTarget == knifefollowanim) {
3627 award_bonus(id, Stabbonus);
3628 XYZ footvel, footpoint;
3630 footpoint = weapons[weaponids[0]].tippoint;
3632 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3633 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3634 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3635 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3636 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3637 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3639 victim->bloodloss += 10000;
3640 victim->velocity = 0;
3641 emit_sound_at(fleshstabsound, victim->coords);
3643 weapons[weaponids[weaponactive]].bloody = 2;
3644 weapons[weaponids[weaponactive]].blooddrip += 5;
3648 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3650 victim->velocity = 0;
3651 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3652 victim->skeleton.joints[i].velocity = 0;
3654 if (animTarget == knifefollowanim) {
3656 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3657 victim->skeleton.joints[i].velocity = 0;
3660 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3661 emit_sound_at(fleshstabremovesound, victim->coords);
3663 weapons[weaponids[weaponactive]].bloody = 2;
3664 weapons[weaponids[weaponactive]].blooddrip += 5;
3666 XYZ footvel, footpoint;
3668 footpoint = weapons[weaponids[0]].tippoint;
3670 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3671 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3672 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3673 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3674 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3675 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3679 if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3680 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3681 award_bonus(id, backstab);
3685 XYZ footvel, footpoint;
3687 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3689 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3690 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3691 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3692 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3693 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3694 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3695 victim->DoBloodBig(200, 180);
3696 victim->DoBloodBig(200, 215);
3697 victim->bloodloss += 10000;
3698 victim->velocity = 0;
3699 emit_sound_at(fleshstabsound, victim->coords);
3701 weapons[weaponids[weaponactive]].bloody = 2;
3702 weapons[weaponids[weaponactive]].blooddrip += 5;
3706 if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3708 victim->velocity = 0;
3709 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3710 victim->skeleton.joints[i].velocity = 0;
3712 if (weaponactive != -1) {
3713 emit_sound_at(fleshstabremovesound, victim->coords);
3715 weapons[weaponids[weaponactive]].bloody = 2;
3716 weapons[weaponids[weaponactive]].blooddrip += 5;
3718 XYZ footvel, footpoint;
3720 footpoint = weapons[weaponids[0]].tippoint;
3722 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3723 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3724 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3725 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3726 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3727 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3731 if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3739 if (weaponactive == -1) {
3740 if (!Tutorial::active) {
3741 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3746 if (weaponactive != -1 || creature == wolftype)
3748 if (creature == rabbittype && weaponactive != -1)
3749 if (weapons[weaponids[0]].getType() == staff)
3752 if (weaponactive != -1) {
3753 victim->DoBloodBig(2 / victim->armorhead, 225);
3754 emit_sound_at(knifeslicesound, victim->coords);
3755 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3756 weapons[weaponids[weaponactive]].bloody = 1;
3757 weapons[weaponids[weaponactive]].blooddrip += 3;
3759 if (weaponactive == -1 && creature == wolftype) {
3760 emit_sound_at(clawslicesound, victim->coords, 128.);
3762 victim->DoBloodBig(2 / victim->armorhead, 175);
3766 award_bonus(id, Reversal);
3771 relative = facing * -1;
3773 Normalise(&relative);
3774 relative = DoRotation(relative, 0, 90, 0);
3776 Normalise(&relative);
3777 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3778 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3780 victim->jointVel(head) += relative * damagemult * 200;
3781 if (victim->damage < victim->damagetolerance - 100)
3782 victim->velocity = relative * 200;
3783 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3784 victim->velocity = 0;
3787 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))) {
3791 relative = facing * -1;
3793 Normalise(&relative);
3794 relative = DoRotation(relative, 0, 90, 0);
3796 Normalise(&relative);
3797 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3798 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3800 victim->jointVel(head) += relative * damagemult * 200;
3803 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3804 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3805 award_bonus(id, reverseko);
3810 if (frameTarget > int(Animation::animations[animCurrent].frames.size()) - 1) {
3813 animTarget = getIdle();
3814 FootLand(leftfoot, 1);
3815 FootLand(rightfoot, 1);
3817 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3818 animTarget = rollanim;
3820 emit_sound_at(movewhooshsound, coords, 128.);
3822 if (animCurrent == staggerbackhighanim) {
3823 animTarget = getIdle();
3825 if (animCurrent == staggerbackhardanim) {
3826 animTarget = getIdle();
3828 if (animCurrent == removeknifeanim) {
3829 animTarget = getIdle();
3831 if (animCurrent == crouchremoveknifeanim) {
3832 animTarget = getCrouch();
3834 if (animCurrent == backhandspringanim) {
3835 animTarget = getIdle();
3837 if (animCurrent == dodgebackanim) {
3838 animTarget = getIdle();
3840 if (animCurrent == drawleftanim) {
3841 animTarget = getIdle();
3843 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3844 animTarget = getIdle();
3845 if (animCurrent == crouchdrawrightanim) {
3846 animTarget = getCrouch();
3848 if (weaponactive == -1)
3850 else if (weaponactive == 0) {
3852 if (num_weapons == 2) {
3854 buffer = weaponids[0];
3855 weaponids[0] = weaponids[1];
3856 weaponids[1] = buffer;
3860 if (weaponactive == -1) {
3861 emit_sound_at(knifesheathesound, coords, 128.);
3863 if (weaponactive != -1) {
3864 emit_sound_at(knifedrawsound, coords, 128.);
3867 if (animCurrent == rollanim) {
3868 animTarget = getCrouch();
3869 FootLand(leftfoot, 1);
3870 FootLand(rightfoot, 1);
3873 if (animTarget == walljumprightkickanim) {
3876 if (animTarget == walljumpleftkickanim) {
3879 animTarget = jumpdownanim;
3881 if (animCurrent == climbanim) {
3882 animTarget = getCrouch();
3884 coords += facing * .1;
3885 if (!isnormal(coords.x))
3895 if (animTarget == rabbitkickreversalanim) {
3896 animTarget = getCrouch();
3899 if (animTarget == jumpreversalanim) {
3900 animTarget = getCrouch();
3903 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3904 if (attackkeydown && animTarget != walljumpfrontanim) {
3906 float closestdist = -1;
3908 if (Person::players.size() > 1)
3909 for (unsigned i = 0; i < Person::players.size(); i++) {
3910 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3911 distance = distsq(&Person::players[i]->coords, &coords);
3912 if (closestdist == -1 || distance < closestdist) {
3913 closestdist = distance;
3918 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3919 victim = Person::players[closest];
3920 animTarget = walljumprightkickanim;
3922 XYZ rotatetarget = victim->coords - coords;
3923 Normalise(&rotatetarget);
3924 yaw = -asin(0 - rotatetarget.x);
3926 if (rotatetarget.z < 0)
3928 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3929 velocity = (victim->coords - coords) * 4;
3934 if (animTarget == walljumpbackanim) {
3935 animTarget = backflipanim;
3937 velocity = facing * -8;
3940 resume_stream(whooshsound);
3942 if (animTarget == walljumprightanim) {
3943 animTarget = rightflipanim;
3947 velocity = DoRotation(facing, 0, 30, 0) * -8;
3950 if (animTarget == walljumpfrontanim) {
3951 animTarget = frontflipanim;
3955 velocity = facing * 8;
3959 resume_stream(whooshsound);
3961 if (animTarget == walljumpleftanim) {
3962 if (attackkeydown) {
3964 float closestdist = -1;
3966 if (Person::players.size() > 1)
3967 for (unsigned i = 0; i < Person::players.size(); i++) {
3968 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3969 distance = distsq(&Person::players[i]->coords, &coords);
3970 if (closestdist == -1 || distance < closestdist) {
3971 closestdist = distance;
3976 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3977 victim = Person::players[closest];
3978 animTarget = walljumpleftkickanim;
3980 XYZ rotatetarget = victim->coords - coords;
3981 Normalise(&rotatetarget);
3982 yaw = -asin(0 - rotatetarget.x);
3984 if (rotatetarget.z < 0)
3986 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3987 velocity = (victim->coords - coords) * 4;
3992 if (animTarget != walljumpleftkickanim) {
3993 animTarget = leftflipanim;
3997 velocity = DoRotation(facing, 0, -30, 0) * -8;
4001 resume_stream(whooshsound);
4003 if (animTarget == sneakattackanim) {
4004 animCurrent = getCrouch();
4005 animTarget = getCrouch();
4012 transspeed = 1000000;
4013 targetheadyaw += 180;
4014 coords -= facing * .7;
4016 coords.y = terrain.getHeight(coords.x, coords.z);
4020 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
4021 animTarget = getIdle();
4024 coords.y = terrain.getHeight(coords.x, coords.z);
4028 if (animCurrent == knifefollowanim) {
4029 animTarget = getIdle();
4032 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
4033 float ycoords = oldcoords.y;
4034 animTarget = getStop();
4039 transspeed = 1000000;
4040 targetheadyaw += 180;
4041 if (!isnormal(coords.x))
4043 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
4044 oldcoords = coords + facing * .5;
4045 else if (animCurrent == sweepreversalanim)
4046 oldcoords = coords + facing * 1.1;
4047 else if (animCurrent == upunchreversalanim) {
4048 oldcoords = coords + facing * 1.5;
4051 targetheadyaw += 180;
4054 } else if (animCurrent == knifeslashreversalanim) {
4055 oldcoords = coords + facing * .5;
4058 targetheadyaw += 90;
4061 } else if (animCurrent == staffspinhitreversalanim) {
4064 targetheadyaw += 180;
4069 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
4071 oldcoords.y = ycoords;
4072 currentoffset = coords - oldcoords;
4078 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4083 if (Animation::animations[animTarget].attack == reversed) {
4085 if (animTarget == sweepreversedanim)
4087 animTarget = backhandspringanim;
4089 emit_sound_at(landsound, coords, 128);
4091 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4092 animTarget = rollanim;
4095 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4096 coords.y = oldcoords.y;
4098 if (animCurrent == knifeslashreversedanim) {
4099 animTarget = rollanim;
4104 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4105 coords.y = oldcoords.y;
4109 animTarget = jumpdownanim;
4112 animTarget = getIdle();
4114 animTarget = getIdle();
4115 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4116 animTarget = getIdle();
4118 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4119 coords.y = oldcoords.y;
4120 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4121 targetoffset.y = coords.y;
4123 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4124 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4125 currentoffset.y -= (coords.y - targetoffset.y);
4126 coords.y = targetoffset.y;
4128 normalsupdatedelay = 0;
4130 if (animCurrent == upunchanim) {
4131 animTarget = getStop();
4132 normalsupdatedelay = 0;
4135 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4139 if (num_weapons > 0)
4140 if (weapons[0].getType() == staff)
4146 rabbitkickragdoll = 1;
4148 if (animCurrent == rabbitkickreversedanim) {
4154 skeleton.spinny = 0;
4155 SolidHitBonus(!id); // FIXME: tricky id
4159 animTarget = rollanim;
4162 pause_sound(whooshsound);
4166 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4170 skeleton.spinny = 0;
4172 if (animCurrent == jumpreversedanim) {
4178 skeleton.spinny = 0;
4179 SolidHitBonus(!id); // FIXME: tricky id
4183 animTarget = rollanim;
4184 coords += facing * 2;
4186 pause_sound(whooshsound);
4191 if (Animation::animations[animCurrent].attack == normalattack && !victim->skeleton.free && victim->animTarget != staggerbackhighanim && victim->animTarget != staggerbackhardanim && animTarget != winduppunchblockedanim && animTarget != blockhighleftanim && animTarget != swordslashparryanim && animTarget != swordslashparriedanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim) {
4192 animTarget = getupfromfrontanim;
4194 } else if (Animation::animations[animCurrent].attack == normalattack) {
4195 animTarget = getIdle();
4198 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4199 animTarget = blockhighleftstrikeanim;
4201 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4202 animTarget = getIdle();
4205 if (animCurrent == spinkickanim && victim->skeleton.free) {
4206 if (creature == rabbittype)
4207 animTarget = fightidleanim;
4212 if (isIdle() && !wasIdle())
4213 normalsupdatedelay = 0;
4215 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4216 animTarget = jumpdownanim;
4219 if (!skeleton.free) {
4221 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4222 if (!isRun() || !wasRun()) {
4223 if (targetFrame().speed > currentFrame().speed)
4224 target += multiplier * targetFrame().speed * speed * 2;
4225 if (targetFrame().speed <= currentFrame().speed)
4226 target += multiplier * currentFrame().speed * speed * 2;
4228 if (isRun() && wasRun()) {
4230 tempspeed = velspeed;
4231 if (tempspeed < 10 * speedmult)
4232 tempspeed = 10 * speedmult;
4233 /* FIXME - mixed of target and current here, is that intended? */
4234 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4236 } else if (transspeed)
4237 target += multiplier * transspeed * speed * 2;
4239 if (!isRun() || !wasRun()) {
4240 if (targetFrame().speed > currentFrame().speed)
4241 target += multiplier * targetFrame().speed * 2;
4242 if (targetFrame().speed <= currentFrame().speed)
4243 target += multiplier * currentFrame().speed * 2;
4247 if (animCurrent != animTarget)
4248 target = (target + oldtarget) / 2;
4251 frameCurrent = frameTarget;
4255 rot = targetrot * target;
4256 yaw += rot - oldrot;
4262 if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
4263 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4265 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4267 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4268 skeleton.joints[i].position = currentFrame().joints[i].position;
4271 skeleton.FindForwards();
4273 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4274 if (skeleton.muscles[i].visible) {
4275 skeleton.FindRotationMuscle(i, animTarget);
4278 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4279 if (skeleton.muscles[i].visible) {
4280 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4281 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4282 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4283 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4284 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4285 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4290 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4291 skeleton.joints[i].position = targetFrame().joints[i].position;
4294 skeleton.FindForwards();
4296 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4297 if (skeleton.muscles[i].visible) {
4298 skeleton.FindRotationMuscle(i, animTarget);
4301 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4302 if (skeleton.muscles[i].visible) {
4303 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4304 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4305 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4306 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4307 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4308 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4309 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180)
4310 skeleton.muscles[i].newrotate3 -= 360;
4311 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180)
4312 skeleton.muscles[i].newrotate3 += 360;
4313 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180)
4314 skeleton.muscles[i].newrotate2 -= 360;
4315 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180)
4316 skeleton.muscles[i].newrotate2 += 360;
4317 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180)
4318 skeleton.muscles[i].newrotate1 -= 360;
4319 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180)
4320 skeleton.muscles[i].newrotate1 += 360;
4325 oldanimCurrent = animCurrent;
4326 oldanimTarget = animTarget;
4327 oldframeTarget = frameTarget;
4328 oldframeCurrent = frameCurrent;
4330 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4331 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target - skeleton.joints[i].position) / multiplier;
4332 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target;
4334 offset = currentoffset * (1 - target) + targetoffset * target;
4335 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4336 if (skeleton.muscles[i].visible) {
4337 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * target;
4338 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * target;
4339 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * target;
4344 if (isLanding() && landhard) {
4347 animTarget = getLandhard();
4360 void Person::DoStuff()
4362 static XYZ terrainnormal;
4363 static XYZ flatfacing;
4364 static XYZ flatvelocity;
4365 static float flatvelspeed;
4366 static int bloodsize;
4367 static int startx, starty, endx, endy;
4368 static GLubyte color;
4369 static XYZ bloodvel;
4371 onfiredelay -= multiplier;
4372 if (onfiredelay < 0 && onfire) {
4373 if (Random() % 2 == 0) {
4379 crouchkeydowntime += multiplier;
4381 crouchkeydowntime = 0;
4382 jumpkeydowntime += multiplier;
4383 if (!jumpkeydown && skeleton.free)
4384 jumpkeydowntime = 0;
4386 if (hostile || damage > 0 || bloodloss > 0)
4389 if (isIdle() || isRun())
4392 if (num_weapons == 1 && weaponactive != -1)
4396 blooddimamount -= multiplier * .3;
4397 speechdelay -= multiplier;
4398 texupdatedelay -= multiplier;
4399 interestdelay -= multiplier;
4400 flamedelay -= multiplier;
4401 parriedrecently -= multiplier;
4403 victim = this->shared_from_this();
4408 speed = 1.1 * speedmult;
4410 speed = 1.0 * speedmult;
4412 rabbitkickragdoll = 0;
4416 if (id != 0 && (creature == rabbittype || difficulty != 2))
4418 if (id != 0 && creature == wolftype && difficulty == 2) {
4420 if (aitype != passivetype) {
4422 if (aitype == attacktypecutoff && (Person::players[0]->isIdle() || Person::players[0]->isCrouch() || Person::players[0]->skeleton.free || Person::players[0]->animTarget == getupfrombackanim || Person::players[0]->animTarget == getupfromfrontanim || Person::players[0]->animTarget == sneakanim) && distsq(&coords, &Person::players[0]->coords) < 16) {
4428 if (animTarget == wolfrunninganim && !superruntoggle) {
4429 animTarget = getRun();
4433 if (weaponactive == -1 && num_weapons > 0) {
4434 if (weapons[weaponids[0]].getType() == staff) {
4440 burnt += multiplier;
4444 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4446 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4452 vel[0] = velocity.x;
4453 vel[1] = velocity.y;
4454 vel[2] = velocity.z;
4457 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
4458 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4462 while (flamedelay < 0 && onfire) {
4464 int howmany = fabs(Random() % (skeleton.joints.size()));
4465 if (skeleton.free) {
4466 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4467 flatfacing = skeleton.joints[howmany].position * scale + coords;
4469 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4470 flatvelocity = (coords - oldcoords) / multiplier / 2;
4472 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4475 while (flamedelay < 0 && !onfire && Tutorial::active && id != 0) {
4477 int howmany = fabs(Random() % (skeleton.joints.size()));
4478 if (skeleton.free) {
4479 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4480 flatfacing = skeleton.joints[howmany].position * scale + coords;
4482 flatvelocity = (coords - oldcoords) / multiplier / 2;
4483 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4485 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4489 bleeding -= multiplier * .3;
4490 if (bloodtoggle == 2) {
4491 skeleton.drawmodel.textureptr.bind();
4492 if ((bleeding <= 0) && (detail != 2))
4497 if (neckspurtamount > 0) {
4498 neckspurtamount -= multiplier;
4499 neckspurtdelay -= multiplier * 3;
4500 neckspurtparticledelay -= multiplier * 3;
4501 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4504 if (skeleton.free) {
4505 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4506 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4507 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4509 bloodvel.z = 5 * neckspurtamount;
4510 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4511 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4512 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4514 neckspurtparticledelay = .05;
4516 if (neckspurtdelay < 0) {
4521 if (deathbleeding > 0 && dead != 2) {
4522 if (deathbleeding < 5)
4523 bleeddelay -= deathbleeding * multiplier / 4;
4525 bleeddelay -= 5 * multiplier / 4;
4526 if (bleeddelay < 0 && bloodtoggle) {
4531 if (skeleton.free) {
4532 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4533 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4535 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4536 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4540 bloodloss += deathbleeding * multiplier * 80;
4541 deathbleeding -= multiplier * 1.6;
4542 if (deathbleeding < 0)
4544 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4545 if (weaponactive != -1) {
4546 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4547 weapons[weaponids[0]].velocity.x += .01;
4550 weaponids[0] = weaponids[num_weapons];
4551 if (weaponstuck == num_weapons)
4555 for (unsigned i = 0; i < Person::players.size(); i++) {
4556 Person::players[i]->wentforweapon = 0;
4564 if (!dead && creature == wolftype) {
4565 award_bonus(0, Wolfbonus);
4568 if (animTarget == knifefollowedanim && !skeleton.free) {
4569 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4570 skeleton.joints[i].velocity = 0;
4571 skeleton.joints[i].velocity.y = -2;
4574 if (id != 0 && unconscioustime > .1) {
4582 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4583 texupdatedelay = .12;
4585 bloodsize = 5 - realtexdetail;
4589 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4590 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4591 endx = startx + bloodsize;
4592 endy = starty + bloodsize;
4602 if (endx > skeleton.skinsize - 1) {
4603 endx = skeleton.skinsize - 1;
4606 if (endy > skeleton.skinsize - 1) {
4607 endy = skeleton.skinsize - 1;
4615 for (int i = startx; i < endx; i++) {
4616 for (int j = starty; j < endy; j++) {
4617 if (Random() % 2 == 0) {
4618 color = Random() % 85 + 170;
4619 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4620 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4621 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4622 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4627 skeleton.drawmodel.textureptr.bind();
4631 if (skeleton.free) {
4632 bleedx += 4 * direction / realtexdetail;
4634 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4636 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4638 bleedy -= 4 / realtexdetail;
4640 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4642 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4646 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4647 righthandmorphness = targetrighthandmorphness;
4648 righthandmorphstart = righthandmorphend;
4649 } else if (righthandmorphness > targetrighthandmorphness) {
4650 righthandmorphness -= multiplier * 4;
4651 } else if (righthandmorphness < targetrighthandmorphness) {
4652 righthandmorphness += multiplier * 4;
4655 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4656 lefthandmorphness = targetlefthandmorphness;
4657 lefthandmorphstart = lefthandmorphend;
4658 } else if (lefthandmorphness > targetlefthandmorphness) {
4659 lefthandmorphness -= multiplier * 4;
4660 } else if (lefthandmorphness < targetlefthandmorphness) {
4661 lefthandmorphness += multiplier * 4;
4664 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4665 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4666 tailmorphness = targettailmorphness;
4667 tailmorphstart = tailmorphend;
4668 } else if (tailmorphness > targettailmorphness) {
4669 tailmorphness -= multiplier * 10;
4670 } else if (tailmorphness < targettailmorphness) {
4671 tailmorphness += multiplier * 10;
4675 if (creature == wolftype) {
4676 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4677 tailmorphness = targettailmorphness;
4678 tailmorphstart = tailmorphend;
4679 } else if (tailmorphness > targettailmorphness) {
4680 tailmorphness -= multiplier * 2;
4681 } else if (tailmorphness < targettailmorphness) {
4682 tailmorphness += multiplier * 2;
4686 if (headmorphend == 3 || headmorphstart == 3) {
4687 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4688 headmorphness = targetheadmorphness;
4689 headmorphstart = headmorphend;
4690 } else if (headmorphness > targetheadmorphness) {
4691 headmorphness -= multiplier * 7;
4692 } else if (headmorphness < targetheadmorphness) {
4693 headmorphness += multiplier * 7;
4695 } else if (headmorphend == 5 || headmorphstart == 5) {
4696 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4697 headmorphness = targetheadmorphness;
4698 headmorphstart = headmorphend;
4699 } else if (headmorphness > targetheadmorphness) {
4700 headmorphness -= multiplier * 10;
4701 } else if (headmorphness < targetheadmorphness) {
4702 headmorphness += multiplier * 10;
4705 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4706 headmorphness = targetheadmorphness;
4707 headmorphstart = headmorphend;
4708 } else if (headmorphness > targetheadmorphness) {
4709 headmorphness -= multiplier * 4;
4710 } else if (headmorphness < targetheadmorphness) {
4711 headmorphness += multiplier * 4;
4715 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4716 chestmorphness = targetchestmorphness;
4717 chestmorphstart = chestmorphend;
4718 } else if (chestmorphness > targetchestmorphness) {
4719 chestmorphness -= multiplier;
4720 } else if (chestmorphness < targetchestmorphness) {
4721 chestmorphness += multiplier;
4724 if (dead != 2 && howactive <= typesleeping) {
4725 if (chestmorphstart == 0 && chestmorphend == 0) {
4727 targetchestmorphness = 1;
4730 if (chestmorphstart != 0 && chestmorphend != 0) {
4732 targetchestmorphness = 1;
4734 if (environment == snowyenvironment) {
4737 if (skeleton.free) {
4738 footvel = skeleton.specialforward[0] * -1;
4739 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4741 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4742 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4744 if (animTarget == sleepanim)
4745 footvel = DoRotation(footvel, 0, 90, 0);
4746 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4750 if (!dead && howactive < typesleeping) {
4751 blinkdelay -= multiplier * 2;
4752 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4754 targetheadmorphness = 1;
4756 blinkdelay = (float)(abs(Random() % 40)) / 5;
4758 if (headmorphstart == 3 && headmorphend == 3) {
4760 targetheadmorphness = 1;
4765 twitchdelay -= multiplier * 1.5;
4766 if (animTarget != hurtidleanim) {
4767 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4769 targetheadmorphness = 1;
4771 twitchdelay = (float)(abs(Random() % 40)) / 5;
4773 if (headmorphstart == 5 && headmorphend == 5) {
4775 targetheadmorphness = 1;
4779 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4780 twitchdelay3 -= multiplier * 1;
4781 if (Random() % 2 == 0) {
4782 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4783 righthandmorphness = 0;
4784 targetrighthandmorphness = 1;
4785 righthandmorphend = 1;
4786 if (Random() % 2 == 0)
4787 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4789 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4790 righthandmorphness = 0;
4791 targetrighthandmorphness = 1;
4792 righthandmorphend = 0;
4795 if (Random() % 2 == 0) {
4796 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4797 lefthandmorphness = 0;
4798 targetlefthandmorphness = 1;
4799 lefthandmorphend = 1;
4800 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4802 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4803 lefthandmorphness = 0;
4804 targetlefthandmorphness = 1;
4805 lefthandmorphend = 0;
4811 if (creature == rabbittype) {
4812 if (howactive < typesleeping)
4813 twitchdelay2 -= multiplier * 1.5;
4815 twitchdelay2 -= multiplier * 0.5;
4816 if (howactive <= typesleeping) {
4817 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4819 targettailmorphness = 1;
4821 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4823 if (tailmorphstart == 1 && tailmorphend == 1) {
4825 targettailmorphness = 1;
4828 if (tailmorphstart == 2 && tailmorphend == 2) {
4830 targettailmorphness = 1;
4837 if (creature == wolftype) {
4838 twitchdelay2 -= multiplier * 1.5;
4839 if (tailmorphend != 0)
4840 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4842 targettailmorphness = 1;
4846 if (tailmorphend != 5)
4847 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4849 targettailmorphness = 1;
4853 if (twitchdelay2 <= 0) {
4854 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4856 targettailmorphness = 1;
4859 if (tailmorphstart == 1 && tailmorphend == 1) {
4861 targettailmorphness = 1;
4864 if (tailmorphstart == 2 && tailmorphend == 2) {
4866 targettailmorphness = 1;
4869 if (tailmorphstart == 3 && tailmorphend == 3) {
4871 targettailmorphness = 1;
4874 if (tailmorphstart == 4 && tailmorphend == 4) {
4876 targettailmorphness = 1;
4883 unconscioustime = 0;
4886 if (dead == 1 || howactive == typesleeping) {
4887 unconscioustime += multiplier;
4888 //If unconscious, close eyes and mouth
4889 if (righthandmorphend != 0)
4890 righthandmorphness = 0;
4891 righthandmorphend = 0;
4892 targetrighthandmorphness = 1;
4894 if (lefthandmorphend != 0)
4895 lefthandmorphness = 0;
4896 lefthandmorphend = 0;
4897 targetlefthandmorphness = 1;
4899 if (headmorphend != 3 && headmorphend != 5)
4902 targetheadmorphness = 1;
4905 if (howactive > typesleeping) {
4908 if (bloodtoggle && !bled) {
4909 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4910 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
4911 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4912 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
4916 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4922 if (dead == 2 || howactive > typesleeping) {
4923 //If dead, open mouth and hands
4924 if (righthandmorphend != 0)
4925 righthandmorphness = 0;
4926 righthandmorphend = 0;
4927 targetrighthandmorphness = 1;
4929 if (lefthandmorphend != 0)
4930 lefthandmorphness = 0;
4931 lefthandmorphend = 0;
4932 targetlefthandmorphness = 1;
4934 if (headmorphend != 2)
4937 targetheadmorphness = 1;
4940 if (stunned > 0 && !dead && headmorphend != 2) {
4941 if (headmorphend != 4)
4944 targetheadmorphness = 1;
4947 if (damage > damagetolerance && !dead) {
4950 unconscioustime = 0;
4952 if (creature == wolftype) {
4953 award_bonus(0, Wolfbonus);
4958 if (weaponactive != -1) {
4959 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4960 weapons[weaponids[0]].velocity.x += .01;
4963 weaponids[0] = weaponids[num_weapons];
4964 if (weaponstuck == num_weapons)
4968 for (unsigned i = 0; i < Person::players.size(); i++) {
4969 Person::players[i]->wentforweapon = 0;
4973 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4982 damage -= multiplier * 13;
4983 permanentdamage -= multiplier * 4;
4984 if (isIdle() || isCrouch()) {
4985 permanentdamage -= multiplier * 4;
4990 if (permanentdamage < 0)
4991 permanentdamage = 0;
4992 if (superpermanentdamage < 0)
4993 superpermanentdamage = 0;
4994 if (permanentdamage < superpermanentdamage) {
4995 permanentdamage = superpermanentdamage;
4997 if (damage < permanentdamage) {
4998 damage = permanentdamage;
5000 if (dead == 1 && damage < damagetolerance) {
5004 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5005 skeleton.joints[i].velocity = 0;
5008 if (permanentdamage > damagetolerance && dead != 2) {
5011 if (weaponactive != -1) {
5012 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5013 weapons[weaponids[0]].velocity.x += .01;
5016 weaponids[0] = weaponids[num_weapons];
5017 if (weaponstuck == num_weapons)
5021 for (unsigned i = 0; i < Person::players.size(); i++) {
5022 Person::players[i]->wentforweapon = 0;
5028 if (!dead && creature == wolftype) {
5029 award_bonus(0, Wolfbonus);
5032 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
5033 award_bonus(id, touchofdeath);
5034 if (id != 0 && unconscioustime > .1) {
5042 emit_sound_at(breaksound, coords);
5045 if (skeleton.free == 1) {
5047 pause_sound(whooshsound);
5050 //If knocked over, open hands and close mouth
5051 if (righthandmorphend != 0)
5052 righthandmorphness = 0;
5053 righthandmorphend = 0;
5054 targetrighthandmorphness = 1;
5056 if (lefthandmorphend != 0)
5057 lefthandmorphness = 0;
5058 lefthandmorphend = 0;
5059 targetlefthandmorphness = 1;
5061 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
5062 if (headmorphend != 0)
5065 targetheadmorphness = 1;
5069 skeleton.DoGravity(&scale);
5071 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
5072 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
5073 award_bonus(id, deepimpact);
5074 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5078 if (!skeleton.joints.empty()) {
5079 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5080 average += skeleton.joints[j].position;
5082 average /= skeleton.joints.size();
5083 coords += average * scale;
5084 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5085 skeleton.joints[j].position -= average;
5087 average /= multiplier;
5091 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5092 velocity += skeleton.joints[i].velocity * scale;
5094 velocity /= skeleton.joints.size();
5096 if (!isnormal(velocity.x) && velocity.x) {
5100 if (findLength(&average) < 10 && dead && skeleton.free) {
5101 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5102 if (skeleton.longdead > 2000) {
5103 if (skeleton.longdead > 6000) {
5105 pause_sound(whooshsound);
5110 if (dead == 2 && bloodloss < damagetolerance) {
5112 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5114 if (bloodtoggle && !bled) {
5115 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5116 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5117 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5118 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5119 float size = .2 * 1.2;
5122 Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5127 if (dead == 2 && bloodloss >= damagetolerance) {
5129 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5132 if (bloodtoggle && !bled) {
5133 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5134 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5135 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5136 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5140 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5148 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5149 bool canrecover = 1;
5150 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5151 startpoint = coords;
5154 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
5156 if (velocity.y < -30)
5158 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5159 if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) {
5160 colviewer = startpoint;
5161 coltarget = endpoint;
5162 if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1)
5171 terrainnormal = jointPos(groin) - jointPos(abdomen);
5172 if (joint(groin).locked && joint(abdomen).locked) {
5173 terrainnormal = jointPos(groin) - jointPos(abdomen);
5174 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5176 if (joint(abdomen).locked && joint(neck).locked) {
5177 terrainnormal = jointPos(abdomen) - jointPos(neck);
5178 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5180 if (joint(groin).locked && joint(neck).locked) {
5181 terrainnormal = jointPos(groin) - jointPos(neck);
5182 middle = (jointPos(groin) + jointPos(neck)) / 2;
5184 Normalise(&terrainnormal);
5186 targetyaw = -asin(0 - terrainnormal.x);
5187 targetyaw *= 360 / 6.28;
5188 if (terrainnormal.z < 0)
5189 targetyaw = 180 - targetyaw;
5193 animTarget = flipanim;
5194 crouchtogglekeydown = 1;
5199 animCurrent = tempanim;
5203 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5204 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5205 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5210 if (findLength(&average) < 10 && !dead && skeleton.free) {
5211 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5212 if (skeleton.longdead > (damage + 500) * 1.5) {
5214 pause_sound(whooshsound);
5220 terrainnormal = jointPos(groin) - jointPos(abdomen);
5221 if (joint(groin).locked && joint(abdomen).locked) {
5222 terrainnormal = jointPos(groin) - jointPos(abdomen);
5223 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5225 if (joint(abdomen).locked && joint(neck).locked) {
5226 terrainnormal = jointPos(abdomen) - jointPos(neck);
5227 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5229 if (joint(groin).locked && joint(neck).locked) {
5230 terrainnormal = jointPos(groin) - jointPos(neck);
5231 middle = (jointPos(groin) + jointPos(neck)) / 2;
5233 Normalise(&terrainnormal);
5235 targetyaw = -asin(0 - terrainnormal.x);
5236 targetyaw *= 360 / 6.28;
5237 if (terrainnormal.z < 0)
5238 targetyaw = 180 - targetyaw;
5241 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5243 if (skeleton.forward.y < 0) {
5244 animTarget = getupfrombackanim;
5248 if (skeleton.forward.y > -.3) {
5249 animTarget = getupfromfrontanim;
5257 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5258 animTarget = rollanim;
5259 targetyaw = lookyaw;
5276 if (!leftkeydown && !rightkeydown)
5283 if (abs(targettilt2) > 50)
5285 animCurrent = tempanim;
5288 tilt2 = targettilt2;
5290 if (middle.y > 0 && animTarget != rollanim)
5291 targetoffset.y = middle.y + 1;
5293 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5294 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5295 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5302 if (num_weapons > 0)
5303 if (weapons[0].getType() == staff)
5305 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5306 if (velocity.y > -30) {
5308 tempvelocity = velocity;
5309 Normalise(&tempvelocity);
5310 targetyaw = -asin(0 - tempvelocity.x);
5311 targetyaw *= 360 / 6.28;
5313 targetyaw = 180 - targetyaw;
5317 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5318 animTarget = rollanim;
5321 animTarget = backhandspringanim;
5327 emit_sound_at(movewhooshsound, coords, 128.);
5329 animCurrent = animTarget;
5330 frameCurrent = frameTarget - 1;
5342 if (skeleton.freefall == 0)
5346 if (aitype != passivetype || skeleton.free == 1)
5347 if (findLengthfast(&velocity) > .1)
5348 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5349 if (Object::objects[i]->type == firetype)
5350 if (distsqflat(&coords, &Object::objects[i]->position) < Object::objects[i]->scale * Object::objects[i]->scale * 12 && distsq(&coords, &Object::objects[i]->position) < Object::objects[i]->scale * Object::objects[i]->scale * 49) {
5352 if (!Object::objects[i]->onfire) {
5353 emit_sound_at(firestartsound, Object::objects[i]->position);
5355 Object::objects[i]->onfire = 1;
5358 if (Object::objects[i]->onfire) {
5363 if (Object::objects[i]->type == bushtype)
5364 if (distsqflat(&coords, &Object::objects[i]->position) < Object::objects[i]->scale * Object::objects[i]->scale * 12 && distsq(&coords, &Object::objects[i]->position) < Object::objects[i]->scale * Object::objects[i]->scale * 49) {
5366 if (!Object::objects[i]->onfire) {
5367 emit_sound_at(firestartsound, Object::objects[i]->position);
5369 Object::objects[i]->onfire = 1;
5373 if (Object::objects[i]->onfire) {
5377 if (Object::objects[i]->messedwith <= 0) {
5381 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5384 addEnvSound(coords, 4 * findLength(&velocity));
5388 if (environment == grassyenvironment)
5389 howmany = findLength(&velocity) * 4;
5390 if (environment == snowyenvironment)
5391 howmany = findLength(&velocity) * 2;
5393 if (environment != desertenvironment)
5394 for (int j = 0; j < howmany; j++) {
5395 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5396 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5397 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5400 pos.x += float(abs(Random() % 100) - 50) / 200;
5401 pos.y += float(abs(Random() % 100) - 50) / 200;
5402 pos.z += float(abs(Random() % 100) - 50) / 200;
5403 Sprite::MakeSprite(splintersprite, pos, tempvel * .5 + velocity * float(abs(Random() % 100)) / 100, 165 / 255 + float(abs(Random() % 100) - 50) / 400, 0, 0, .2 + float(abs(Random() % 100) - 50) / 1300, 1);
5404 Sprite::setLastSpriteSpecial(1);
5406 howmany = findLength(&velocity) * 4;
5408 if (environment == snowyenvironment)
5409 for (int j = 0; j < howmany; j++) {
5410 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5411 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5412 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5415 pos.x += float(abs(Random() % 100) - 50) / 200;
5416 pos.y += float(abs(Random() % 100) - 50) / 200;
5417 pos.z += float(abs(Random() % 100) - 50) / 200;
5418 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5419 Sprite::setLastSpriteSpecial(2);
5422 Object::objects[i]->rotx += velocity.x * multiplier * 6;
5423 Object::objects[i]->roty += velocity.z * multiplier * 6;
5424 Object::objects[i]->messedwith = .5;
5427 if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) {
5428 if (Object::objects[i]->pitch == 0)
5431 tempcoord = coords - Object::objects[i]->position;
5432 tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0);
5433 tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0);
5434 tempcoord += Object::objects[i]->position;
5436 if (distsqflat(&tempcoord, &Object::objects[i]->position) < Object::objects[i]->scale * Object::objects[i]->scale * 8 && distsq(&tempcoord, &Object::objects[i]->position) < Object::objects[i]->scale * Object::objects[i]->scale * 300 && tempcoord.y > Object::objects[i]->position.y + 3 * Object::objects[i]->scale) {
5437 if (Object::objects[i]->messedwith <= 0) {
5441 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5444 addEnvSound(coords, 4 * findLength(&velocity));
5448 if (environment == grassyenvironment)
5449 howmany = findLength(&velocity) * 4;
5450 if (environment == snowyenvironment)
5451 howmany = findLength(&velocity) * 2;
5453 if (environment != desertenvironment)
5454 for (int j = 0; j < howmany; j++) {
5455 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5456 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5457 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5459 pos += velocity * .1;
5461 pos.x += float(abs(Random() % 100) - 50) / 150;
5462 pos.y += float(abs(Random() % 100) - 50) / 150;
5463 pos.z += float(abs(Random() % 100) - 50) / 150;
5464 Sprite::MakeSprite(splintersprite, pos, tempvel * .5 + velocity * float(abs(Random() % 100)) / 100, 165 / 255 + float(abs(Random() % 100) - 50) / 400, 0, 0, .2 + float(abs(Random() % 100) - 50) / 1300, 1);
5465 Sprite::setLastSpriteSpecial(1);
5467 howmany = findLength(&velocity) * 4;
5469 if (environment == snowyenvironment)
5470 for (int j = 0; j < howmany; j++) {
5471 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5472 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5473 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5475 pos += velocity * .1;
5477 pos.x += float(abs(Random() % 100) - 50) / 150;
5478 pos.y += float(abs(Random() % 100) - 50) / 150;
5479 pos.z += float(abs(Random() % 100) - 50) / 150;
5480 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5481 Sprite::setLastSpriteSpecial(2);
5484 Object::objects[i]->messedwith = .5;
5489 if (!skeleton.free) {
5492 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5495 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5497 if (Tutorial::active && id != 0)
5499 if (play && aitype != playercontrolled) {
5500 int whichsound = -1;
5501 if (speechdelay <= 0) {
5502 unsigned int i = abs(Random() % 4);
5503 if (creature == rabbittype) {
5505 whichsound = rabbitchitter;
5507 whichsound = rabbitchitter2;
5509 if (creature == wolftype) {
5511 whichsound = growlsound;
5513 whichsound = growl2sound;
5518 if (whichsound != -1) {
5519 emit_sound_at(whichsound, coords);
5523 if (animTarget == staggerbackhighanim)
5525 if (animTarget == staggerbackhardanim)
5527 staggerdelay -= multiplier;
5528 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5530 if (velocity.y < -30 && animTarget == jumpdownanim)
5532 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5533 animTarget = getIdle();
5537 weaponmissdelay -= multiplier;
5538 highreversaldelay -= multiplier;
5539 lowreversaldelay -= multiplier;
5540 lastcollide -= multiplier;
5541 skiddelay -= multiplier;
5542 if (!isnormal(velocity.x) && velocity.x) {
5545 if (!isnormal(targettilt) && targettilt) {
5548 if (!isnormal(targettilt2) && targettilt2) {
5551 if (!isnormal(targetyaw) && targetyaw) {
5555 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5556 //open hands and close mouth
5557 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5558 righthandmorphness = 0;
5559 righthandmorphend = 0;
5560 targetrighthandmorphness = 1;
5563 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5564 lefthandmorphness = 0;
5565 lefthandmorphend = 0;
5566 targetlefthandmorphness = 1;
5569 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5572 targetheadmorphness = 1;
5576 if (animTarget == rollanim || animTarget == dodgebackanim || animTarget == removeknifeanim || animTarget == knifefightidleanim || animTarget == swordfightidleanim || animTarget == blockhighleftstrikeanim || animTarget == crouchremoveknifeanim || animTarget == sneakanim || animTarget == sweepanim || animTarget == spinkickreversedanim || animTarget == jumpdownanim || isWallJump() || isFlip() || animTarget == climbanim || isRun() || animTarget == getupfrombackanim || animTarget == getupfromfrontanim) {
5577 //open hands and mouth
5578 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5579 righthandmorphness = 0;
5580 righthandmorphend = 0;
5581 targetrighthandmorphness = 1;
5584 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5585 lefthandmorphness = 0;
5586 lefthandmorphend = 0;
5587 targetlefthandmorphness = 1;
5590 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5593 targetheadmorphness = 1;
5597 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5598 //close hands and mouth
5599 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5600 righthandmorphness = 0;
5601 righthandmorphend = 1;
5602 targetrighthandmorphness = 1;
5605 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5606 lefthandmorphness = 0;
5607 lefthandmorphend = 1;
5608 targetlefthandmorphness = 1;
5611 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5614 targetheadmorphness = 1;
5618 if (animTarget == spinkickanim ||
5619 animTarget == staffspinhitreversalanim ||
5620 animTarget == staffspinhitreversedanim ||
5621 animTarget == staffhitreversalanim ||
5622 animTarget == staffhitreversedanim ||
5623 animTarget == hurtidleanim ||
5624 animTarget == winduppunchanim ||
5625 animTarget == swordslashreversalanim ||
5626 animTarget == swordslashreversedanim ||
5627 animTarget == knifeslashreversalanim ||
5628 animTarget == knifeslashreversedanim ||
5629 animTarget == knifethrowanim ||
5630 animTarget == knifefollowanim ||
5631 animTarget == knifefollowedanim ||
5632 animTarget == killanim ||
5633 animTarget == dropkickanim ||
5634 animTarget == upunchanim ||
5635 animTarget == knifeslashstartanim ||
5636 animTarget == swordslashanim ||
5637 animTarget == staffhitanim ||
5638 animTarget == staffspinhitanim ||
5639 animTarget == staffgroundsmashanim ||
5640 animTarget == spinkickreversalanim ||
5641 animTarget == sweepreversalanim ||
5642 animTarget == lowkickanim ||
5643 animTarget == sweepreversedanim ||
5644 animTarget == rabbitkickreversalanim ||
5645 animTarget == rabbitkickreversedanim ||
5646 animTarget == jumpreversalanim ||
5647 animTarget == jumpreversedanim) {
5648 //close hands and yell
5649 if (righthandmorphend != 1 &&
5650 righthandmorphness == targetrighthandmorphness) {
5651 righthandmorphness = 0;
5652 righthandmorphend = 1;
5653 targetrighthandmorphness = 1;
5656 if (lefthandmorphend != 1 &&
5657 lefthandmorphness == targetlefthandmorphness) {
5658 lefthandmorphness = 0;
5659 lefthandmorphend = 1;
5660 targetlefthandmorphness = 1;
5663 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5666 targetheadmorphness = 1;
5673 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5674 (victim->aitype != searchtype) && (aitype != passivetype) &&
5675 (aitype != searchtype) && (victim->id < Person::players.size())) {
5676 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5680 if (!dead && animTarget != hurtidleanim)
5681 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5682 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5685 targetheadmorphness = 1;
5689 if (weaponactive != -1) {
5690 if (weapons[weaponids[weaponactive]].getType() != staff) {
5691 righthandmorphstart = 1;
5692 righthandmorphend = 1;
5694 if (weapons[weaponids[weaponactive]].getType() == staff) {
5695 righthandmorphstart = 2;
5696 righthandmorphend = 2;
5698 targetrighthandmorphness = 1;
5701 terrainnormal = terrain.getNormal(coords.x, coords.z);
5703 if (Animation::animations[animTarget].attack != reversal) {
5704 if (!isnormal(coords.x))
5712 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5713 facing = flatfacing;
5714 ReflectVector(&facing, terrainnormal);
5718 animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5720 targettilt2 = -facing.y * 20;
5725 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5727 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5728 flatvelocity = velocity;
5730 flatvelspeed = findLength(&flatvelocity);
5731 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5732 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5737 if (targettilt > 25)
5739 if (targettilt < -25)
5743 if (targettilt2 > 45)
5745 if (targettilt2 < -45)
5747 if (abs(tilt2 - targettilt2) < multiplier * 400)
5748 tilt2 = targettilt2;
5749 else if (tilt2 > targettilt2) {
5750 tilt2 -= multiplier * 400;
5751 } else if (tilt2 < targettilt2) {
5752 tilt2 += multiplier * 400;
5754 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5761 if (!isnormal(targettilt) && targettilt) {
5764 if (!isnormal(targettilt2) && targettilt2) {
5769 if (animTarget == rabbittackleanim) {
5770 velocity += facing * multiplier * speed * 700 * scale;
5771 velspeed = findLength(&velocity);
5772 if (velspeed > speed * 65 * scale) {
5773 velocity /= velspeed;
5774 velspeed = speed * 65 * scale;
5775 velocity *= velspeed;
5777 velocity.y += gravity * multiplier * 20;
5778 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5779 velspeed = findLength(&velocity);
5780 velocity = flatfacing * velspeed;
5782 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5783 if (isRun() || animTarget == rabbitkickanim) {
5784 velocity += facing * multiplier * speed * 700 * scale;
5785 velspeed = findLength(&velocity);
5786 if (velspeed > speed * 45 * scale) {
5787 velocity /= velspeed;
5788 velspeed = speed * 45 * scale;
5789 velocity *= velspeed;
5791 velocity.y += gravity * multiplier * 20;
5792 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5793 velspeed = findLength(&velocity);
5794 if (velspeed < speed * 30 * scale)
5795 velspeed = speed * 30 * scale;
5796 velocity = flatfacing * velspeed;
5798 } else if (isRun()) {
5799 velocity += facing * multiplier * speed * 700 * scale;
5800 velspeed = findLength(&velocity);
5801 if (creature == rabbittype) {
5802 if (velspeed > speed * 55 * scale) {
5803 velocity /= velspeed;
5804 velspeed = speed * 55 * scale;
5805 velocity *= velspeed;
5808 if (creature == wolftype) {
5809 if (velspeed > speed * 75 * scale) {
5810 velocity /= velspeed;
5811 velspeed = speed * 75 * scale;
5812 velocity *= velspeed;
5815 velocity.y += gravity * multiplier * 20;
5816 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5817 velspeed = findLength(&velocity);
5818 velocity = flatfacing * velspeed;
5821 if (animTarget == rollanim && targetFrame().label != 6) {
5822 velocity += facing * multiplier * speed * 700 * scale;
5823 velspeed = findLength(&velocity);
5824 if (velspeed > speed * 45 * scale) {
5825 velocity /= velspeed;
5826 velspeed = speed * 45 * scale;
5827 velocity *= velspeed;
5829 velocity.y += gravity * multiplier * 20;
5830 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5831 velspeed = findLength(&velocity);
5832 velocity = flatfacing * velspeed;
5835 if (animTarget == sneakanim || animTarget == walkanim) {
5836 velocity += facing * multiplier * speed * 700 * scale;
5837 velspeed = findLength(&velocity);
5838 if (velspeed > speed * 12 * scale) {
5839 velocity /= velspeed;
5840 velspeed = speed * 12 * scale;
5841 velocity *= velspeed;
5843 velocity.y += gravity * multiplier * 20;
5844 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5845 velspeed = findLength(&velocity);
5846 velocity = flatfacing * velspeed;
5849 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5850 velocity += facing * multiplier * speed * 700 * scale;
5851 velspeed = findLength(&velocity);
5852 if (velspeed > speed * 2 * scale) {
5853 velocity /= velspeed;
5854 velspeed = speed * 2 * scale;
5855 velocity *= velspeed;
5857 velocity.y += gravity * multiplier * 20;
5858 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5859 velspeed = findLength(&velocity);
5860 velocity = flatfacing * velspeed;
5863 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5864 velocity -= facing * multiplier * speed * 700 * scale;
5865 velspeed = findLength(&velocity);
5866 if (velspeed > speed * 2 * scale) {
5867 velocity /= velspeed;
5868 velspeed = speed * 2 * scale;
5869 velocity *= velspeed;
5871 velocity.y += gravity * multiplier * 20;
5872 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5873 velspeed = findLength(&velocity);
5874 velocity = flatfacing * velspeed * -1;
5877 if (animTarget == fightsidestep) {
5878 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5879 velspeed = findLength(&velocity);
5880 if (velspeed > speed * 12 * scale) {
5881 velocity /= velspeed;
5882 velspeed = speed * 12 * scale;
5883 velocity *= velspeed;
5885 velocity.y += gravity * multiplier * 20;
5886 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5887 velspeed = findLength(&velocity);
5888 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5891 if (animTarget == staggerbackhighanim) {
5892 coords -= facing * multiplier * speed * 16 * scale;
5895 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
5896 coords -= facing * multiplier * speed * 20 * scale;
5900 if (animTarget == backhandspringanim) {
5901 //coords-=facing*multiplier*50*scale;
5902 velocity += facing * multiplier * speed * 700 * scale * -1;
5903 velspeed = findLength(&velocity);
5904 if (velspeed > speed * 50 * scale) {
5905 velocity /= velspeed;
5906 velspeed = speed * 50 * scale;
5907 velocity *= velspeed;
5909 velocity.y += gravity * multiplier * 20;
5910 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5911 velspeed = findLength(&velocity);
5912 velocity = flatfacing * velspeed * -1;
5914 if (animTarget == dodgebackanim) {
5915 //coords-=facing*multiplier*50*scale;
5916 velocity += facing * multiplier * speed * 700 * scale * -1;
5917 velspeed = findLength(&velocity);
5918 if (velspeed > speed * 60 * scale) {
5919 velocity /= velspeed;
5920 velspeed = speed * 60 * scale;
5921 velocity *= velspeed;
5923 velocity.y += gravity * multiplier * 20;
5924 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5925 velspeed = findLength(&velocity);
5926 velocity = flatfacing * velspeed * -1;
5929 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5930 velspeed = findLength(&velocity);
5933 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5934 velocity.y += gravity * multiplier;
5937 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5938 coords += velocity * multiplier;
5940 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5941 if (isFlip() && targetFrame().label == 7)
5944 if (animTarget == jumpupanim) {
5946 animTarget = getIdle();
5953 pause_sound(whooshsound);
5954 OPENAL_SetVolume(channels[whooshsound], 0);
5957 if (animTarget == jumpdownanim || isFlip()) {
5960 animTarget = getLanding();
5961 emit_sound_at(landsound, coords, 128.);
5964 addEnvSound(coords);
5969 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5970 coords.y += gravity * multiplier * 2;
5971 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5972 coords.y = terrain.getHeight(coords.x, coords.z);
5976 if (isIdle() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || isStop() || animTarget == removeknifeanim || animTarget == crouchremoveknifeanim || isLanding() || isCrouch() || Animation::animations[animTarget].attack || (animTarget == rollanim && targetFrame().label == 6)) {
5977 velspeed = findLength(&velocity);
5979 if (velspeed < multiplier * 300 * scale) {
5982 velocity -= velocity / velspeed * multiplier * 300 * scale;
5984 if (velspeed > 5 && (isLanding() || isLandhard())) {
5985 skiddingdelay += multiplier;
5986 if (skiddelay <= 0) {
5987 FootLand(leftfoot, .5);
5988 FootLand(rightfoot, .5);
5997 velspeed = findLength(&velocity);
5999 if (velspeed > 5 && (isLanding() || isLandhard())) {
6000 skiddingdelay += multiplier;
6001 if (skiddelay <= 0) {
6002 FootLand(leftfoot, .5);
6003 FootLand(rightfoot, .5);
6011 if (skiddingdelay < 0)
6012 skiddingdelay += multiplier;
6013 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
6015 if (!onterrain || environment == grassyenvironment) {
6016 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
6018 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
6022 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
6023 terrainnormal = victim->coords - coords;
6024 Normalise(&terrainnormal);
6025 targetyaw = -asin(0 - terrainnormal.x);
6026 targetyaw *= 360 / 6.28;
6027 if (terrainnormal.z < 0)
6028 targetyaw = 180 - targetyaw;
6029 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
6032 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
6033 targetyaw = victim->targetyaw;
6035 if (animTarget == rabbittacklinganim) {
6036 coords = victim->coords;
6039 skeleton.oldfree = skeleton.free;
6043 midterrain.x = terrain.size * terrain.scale / 2;
6044 midterrain.z = terrain.size * terrain.scale / 2;
6045 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
6047 tempposit = coords - midterrain;
6049 Normalise(&tempposit);
6050 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
6051 coords.x = tempposit.x + midterrain.x;
6052 coords.z = tempposit.z + midterrain.z;
6057 * inverse kinematics helper function
6059 void IKHelper(Person* p, float interp)
6061 XYZ point, change, change2;
6062 float heightleft, heightright;
6064 // TODO: implement localToWorld and worldToLocal
6065 // but keep in mind it won't be the same math if player is ragdolled or something
6066 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
6067 // then comb through code for places where to use it
6069 // point = localToWorld(jointPos(leftfoot))
6070 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
6071 // adjust height of foot
6072 heightleft = terrain.getHeight(point.x, point.z) + .04;
6073 point.y = heightleft;
6074 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
6075 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
6076 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
6077 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
6078 // move ankle along with foot
6079 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
6080 // average knee pos between old and new pos
6081 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
6083 // do same as above for right leg
6084 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
6085 heightright = terrain.getHeight(point.x, point.z) + .04;
6086 point.y = heightright;
6087 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
6088 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
6089 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
6090 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
6091 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
6093 // fix up skeleton now that we've moved body parts?
6094 p->skeleton.DoConstraints(&p->coords, &p->scale);
6101 int Person::DrawSkeleton()
6103 int oldplayerdetail;
6104 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6105 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6115 glAlphaFunc(GL_GREATER, 0.0001);
6117 float terrainheight;
6121 if (!isnormal(tilt))
6123 if (!isnormal(tilt2))
6125 oldplayerdetail = playerdetail;
6127 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6130 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6133 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6138 if (playerdetail != oldplayerdetail) {
6140 normalsupdatedelay = 0;
6142 static float updatedelaychange;
6143 static float morphness;
6144 static float framemult;
6146 skeleton.FindForwards();
6147 if (howactive == typesittingwall) {
6148 skeleton.specialforward[1] = 0;
6149 skeleton.specialforward[1].z = 1;
6155 static int weaponattachmuscle;
6156 static int weaponrotatemuscle;
6157 static XYZ weaponpoint;
6158 static int start, endthing;
6159 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6160 if (!isSleeping() && !isSitting()) {
6161 // TODO: give these meaningful names
6162 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6163 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard() || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6165 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6167 if (creature == wolftype)
6171 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6172 IKHelper(this, target);
6173 if (creature == wolftype)
6174 IKHelper(this, target);
6177 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6178 IKHelper(this, 1 - target);
6179 if (creature == wolftype)
6180 IKHelper(this, 1 - target);
6184 if (!skeleton.free && (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && ((animTarget != rollanim && !isFlip()) || targetFrame().label == 6) && animTarget != getupfromfrontanim && animTarget != wolfrunninganim && animTarget != rabbitrunninganim && animTarget != backhandspringanim && animTarget != walljumpfrontanim && animTarget != hurtidleanim && !isLandhard() && !isSleeping()))
6187 targetheadyaw = -targetyaw;
6188 targetheadpitch = 0;
6189 if (Animation::animations[animTarget].attack == 3)
6190 targetheadyaw += 180;
6192 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6193 skeleton.drawmodel.vertex[i] = 0;
6194 skeleton.drawmodel.vertex[i].y = 999;
6196 for (int i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6197 skeleton.drawmodellow.vertex[i] = 0;
6198 skeleton.drawmodellow.vertex[i].y = 999;
6200 for (int i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6201 skeleton.drawmodelclothes.vertex[i] = 0;
6202 skeleton.drawmodelclothes.vertex[i].y = 999;
6204 for (unsigned int i = 0; i < skeleton.muscles.size(); i++) {
6205 // convenience renames
6206 const int p1 = skeleton.muscles[i].parent1->label;
6207 const int p2 = skeleton.muscles[i].parent2->label;
6209 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6214 if (p1 == righthand || p2 == righthand) {
6215 morphness = righthandmorphness;
6216 start = righthandmorphstart;
6217 endthing = righthandmorphend;
6219 if (p1 == lefthand || p2 == lefthand) {
6220 morphness = lefthandmorphness;
6221 start = lefthandmorphstart;
6222 endthing = lefthandmorphend;
6224 if (p1 == head || p2 == head) {
6225 morphness = headmorphness;
6226 start = headmorphstart;
6227 endthing = headmorphend;
6229 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6230 morphness = chestmorphness;
6231 start = chestmorphstart;
6232 endthing = chestmorphend;
6234 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6235 morphness = tailmorphness;
6236 start = tailmorphstart;
6237 endthing = tailmorphend;
6240 skeleton.FindRotationMuscle(i, animTarget);
6241 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6242 glMatrixMode(GL_MODELVIEW);
6246 glRotatef(tilt2, 1, 0, 0);
6248 glRotatef(tilt, 0, 0, 1);
6250 glTranslatef(mid.x, mid.y, mid.z);
6252 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6253 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6255 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6256 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6258 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6259 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6261 if (playerdetail || skeleton.free == 3) {
6262 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6263 XYZ& v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6264 XYZ& v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6265 glMatrixMode(GL_MODELVIEW);
6267 if (p1 == abdomen || p2 == abdomen)
6268 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6269 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6270 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6271 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6272 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6273 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6274 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6275 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6276 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6277 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6278 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6279 if (p1 == head || p2 == head)
6280 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6281 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6282 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6283 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6284 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6285 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6286 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6290 if (!playerdetail || skeleton.free == 3) {
6291 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6292 XYZ& v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6293 glMatrixMode(GL_MODELVIEW);
6295 if (p1 == abdomen || p2 == abdomen)
6296 glTranslatef(v0.x * proportionbody.x,
6297 v0.y * proportionbody.y,
6298 v0.z * proportionbody.z);
6299 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6300 glTranslatef(v0.x * proportionarms.x,
6301 v0.y * proportionarms.y,
6302 v0.z * proportionarms.z);
6303 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6304 glTranslatef(v0.x * proportionlegs.x,
6305 v0.y * proportionlegs.y,
6306 v0.z * proportionlegs.z);
6307 if (p1 == head || p2 == head)
6308 glTranslatef(v0.x * proportionhead.x,
6309 v0.y * proportionhead.y,
6310 v0.z * proportionhead.z);
6312 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6313 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6314 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6315 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6321 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6322 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6324 glMatrixMode(GL_MODELVIEW);
6328 glRotatef(tilt2, 1, 0, 0);
6330 glRotatef(tilt, 0, 0, 1);
6331 glTranslatef(mid.x, mid.y, mid.z);
6332 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6333 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6335 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6336 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6338 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6339 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6341 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6342 XYZ& v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6343 glMatrixMode(GL_MODELVIEW);
6345 if (p1 == abdomen || p2 == abdomen)
6346 glTranslatef(v0.x * proportionbody.x,
6347 v0.y * proportionbody.y,
6348 v0.z * proportionbody.z);
6349 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6350 glTranslatef(v0.x * proportionarms.x,
6351 v0.y * proportionarms.y,
6352 v0.z * proportionarms.z);
6353 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6354 glTranslatef(v0.x * proportionlegs.x,
6355 v0.y * proportionlegs.y,
6356 v0.z * proportionlegs.z);
6357 if (p1 == head || p2 == head)
6358 glTranslatef(v0.x * proportionhead.x,
6359 v0.y * proportionhead.y,
6360 v0.z * proportionhead.z);
6361 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6362 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6363 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6364 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6369 updatedelay = 1 + (float)(Random() % 100) / 1000;
6371 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6372 normalsupdatedelay = 1;
6373 if (playerdetail || skeleton.free == 3)
6374 skeleton.drawmodel.CalculateNormals(0);
6375 if (!playerdetail || skeleton.free == 3)
6376 skeleton.drawmodellow.CalculateNormals(0);
6377 if (skeleton.clothes)
6378 skeleton.drawmodelclothes.CalculateNormals(0);
6380 if (playerdetail || skeleton.free == 3)
6381 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6382 if (!playerdetail || skeleton.free == 3)
6383 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6384 if (skeleton.clothes) {
6385 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6390 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6391 if (updatedelaychange > -realmultiplier * 30)
6392 updatedelaychange = -realmultiplier * 30;
6393 if (updatedelaychange > -framemult * 4)
6394 updatedelaychange = -framemult * 4;
6395 if (skeleton.free == 1)
6396 updatedelaychange *= 6;
6398 updatedelaychange *= 8;
6399 updatedelay += updatedelaychange;
6401 glMatrixMode(GL_MODELVIEW);
6403 glTranslatef(coords.x, coords.y - .02, coords.z);
6404 if (!skeleton.free) {
6405 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6406 glRotatef(yaw, 0, 1, 0);
6410 glColor4f(.4, 1, .4, 1);
6411 glDisable(GL_LIGHTING);
6412 glDisable(GL_TEXTURE_2D);
6415 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6416 XYZ& v0 = skeleton.drawmodel.vertex[i];
6417 glVertex3f(v0.x, v0.y, v0.z);
6424 for (unsigned int i = 0; i < skeleton.drawmodel.Triangles.size(); i++) {
6425 const XYZ& v0 = skeleton.drawmodel.getTriangleVertex(i, 0);
6426 const XYZ& v1 = skeleton.drawmodel.getTriangleVertex(i, 1);
6427 const XYZ& v2 = skeleton.drawmodel.getTriangleVertex(i, 2);
6428 glVertex3f(v0.x, v0.y, v0.z);
6429 glVertex3f(v1.x, v1.y, v1.z);
6430 glVertex3f(v1.x, v1.y, v1.z);
6431 glVertex3f(v2.x, v2.y, v2.z);
6432 glVertex3f(v2.x, v2.y, v2.z);
6433 glVertex3f(v0.x, v0.y, v0.z);
6440 terrainlight = terrain.getLighting(coords.x, coords.z);
6441 distance = distsq(&viewer, &coords);
6442 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6446 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6447 if (terrainheight < 1)
6449 if (terrainheight > 1.7)
6450 terrainheight = 1.7;
6452 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6453 glDisable(GL_BLEND);
6454 glAlphaFunc(GL_GREATER, 0.0001);
6455 glEnable(GL_TEXTURE_2D);
6457 glDisable(GL_TEXTURE_2D);
6458 glColor4f(.7, .35, 0, .5);
6460 glEnable(GL_LIGHTING);
6463 if (Tutorial::active && id != 0) {
6464 glColor4f(.7, .7, .7, 0.6);
6466 glEnable(GL_LIGHTING);
6468 if (canattack && cananger)
6469 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6470 glDisable(GL_TEXTURE_2D);
6471 glColor4f(1, 0, 0, 0.8);
6473 glMatrixMode(GL_TEXTURE);
6475 glTranslatef(0, -smoketex, 0);
6476 glTranslatef(-smoketex, 0, 0);
6480 if (Tutorial::active && (id != 0))
6481 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6483 skeleton.drawmodel.draw();
6486 if (!playerdetail) {
6487 if (Tutorial::active && (id != 0))
6488 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6490 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6493 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed))
6494 if (Tutorial::active && id != 0) {
6496 glMatrixMode(GL_MODELVIEW);
6497 glEnable(GL_TEXTURE_2D);
6498 glColor4f(.7, .7, .7, 0.6);
6500 glEnable(GL_LIGHTING);
6502 if (canattack && cananger)
6503 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6504 glDisable(GL_TEXTURE_2D);
6505 glColor4f(1, 0, 0, 0.8);
6507 glMatrixMode(GL_TEXTURE);
6509 glTranslatef(0, -smoketex * .6, 0);
6510 glTranslatef(smoketex * .6, 0, 0);
6513 if (Tutorial::active && (id != 0))
6514 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6516 skeleton.drawmodel.draw();
6519 if (!playerdetail) {
6520 if (Tutorial::active && (id != 0))
6521 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6523 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6527 if (Tutorial::active && id != 0) {
6529 glMatrixMode(GL_MODELVIEW);
6530 glEnable(GL_TEXTURE_2D);
6532 if (skeleton.clothes) {
6536 skeleton.drawmodelclothes.draw();
6538 skeleton.drawmodelclothes.drawimmediate();
6544 if (num_weapons > 0) {
6545 for (k = 0; k < num_weapons; k++) {
6546 int i = weaponids[k];
6547 if (weaponactive == k) {
6548 if (weapons[i].getType() != staff) {
6549 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6550 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6551 weaponattachmuscle = j;
6554 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6555 if ((skeleton.muscles[j].parent1->label == rightwrist || skeleton.muscles[j].parent2->label == rightwrist) && (skeleton.muscles[j].parent1->label != righthand && skeleton.muscles[j].parent2->label != righthand) && skeleton.muscles[j].vertices.size() > 0) {
6556 weaponrotatemuscle = j;
6559 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6560 if (creature == wolftype)
6561 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6563 if (weapons[i].getType() == staff) {
6564 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6565 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6566 weaponattachmuscle = j;
6569 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6570 if ((skeleton.muscles[j].parent1->label == rightelbow || skeleton.muscles[j].parent2->label == rightelbow) && (skeleton.muscles[j].parent1->label != rightshoulder && skeleton.muscles[j].parent2->label != rightshoulder) && skeleton.muscles[j].vertices.size() > 0) {
6571 weaponrotatemuscle = j;
6574 //weaponpoint=jointPos(rightwrist);
6575 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6576 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6577 XYZ tempnormthing, vec1, vec2;
6578 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6579 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6580 CrossProduct(&vec1, &vec2, &tempnormthing);
6581 Normalise(&tempnormthing);
6582 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6583 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6586 if (weaponactive != k && weaponstuck != k) {
6587 if (weapons[i].getType() == knife)
6588 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6589 if (weapons[i].getType() == sword)
6590 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6591 if (weapons[i].getType() == staff)
6592 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6593 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6594 if ((skeleton.muscles[j].parent1->label == abdomen || skeleton.muscles[j].parent2->label == abdomen) && (skeleton.muscles[j].parent1->label == neck || skeleton.muscles[j].parent2->label == neck) && skeleton.muscles[j].vertices.size() > 0) {
6595 weaponrotatemuscle = j;
6599 if (weaponstuck == k) {
6600 if (weaponstuckwhere == 0)
6601 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6603 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6604 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6605 if ((skeleton.muscles[j].parent1->label == abdomen || skeleton.muscles[j].parent2->label == abdomen) && (skeleton.muscles[j].parent1->label == neck || skeleton.muscles[j].parent2->label == neck) && skeleton.muscles[j].vertices.size() > 0) {
6606 weaponrotatemuscle = j;
6610 if (skeleton.free) {
6611 weapons[i].position = weaponpoint * scale + coords;
6612 weapons[i].bigrotation = 0;
6613 weapons[i].bigtilt = 0;
6614 weapons[i].bigtilt2 = 0;
6616 weapons[i].position = DoRotation(DoRotation(DoRotation(weaponpoint, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords + currentoffset * (1 - target) * scale + targetoffset * target * scale;
6617 weapons[i].bigrotation = yaw;
6618 weapons[i].bigtilt = tilt;
6619 weapons[i].bigtilt2 = tilt2;
6621 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6622 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6623 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6624 if (weaponactive == k) {
6625 if (weapons[i].getType() == knife) {
6626 weapons[i].smallrotation = 180;
6627 weapons[i].smallrotation2 = 0;
6628 if (isCrouch() || wasCrouch()) {
6629 weapons[i].smallrotation2 = 20;
6631 if (animTarget == hurtidleanim) {
6632 weapons[i].smallrotation2 = 50;
6634 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6635 XYZ temppoint1, temppoint2;
6638 temppoint1 = jointPos(righthand);
6639 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6640 distance = findDistance(&temppoint1, &temppoint2);
6641 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6642 weapons[i].rotation2 *= 360 / 6.28;
6645 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6646 weapons[i].rotation1 *= 360 / 6.28;
6647 weapons[i].rotation3 = 0;
6648 weapons[i].smallrotation = -90;
6649 weapons[i].smallrotation2 = 0;
6650 if (temppoint1.x > temppoint2.x)
6651 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6653 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6654 XYZ temppoint1, temppoint2;
6657 temppoint1 = jointPos(righthand);
6658 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6659 distance = findDistance(&temppoint1, &temppoint2);
6660 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6661 weapons[i].rotation2 *= 360 / 6.28;
6664 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6665 weapons[i].rotation1 *= 360 / 6.28;
6666 weapons[i].rotation3 = 0;
6667 weapons[i].smallrotation = 90;
6668 weapons[i].smallrotation2 = 0;
6669 if (temppoint1.x > temppoint2.x)
6670 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6672 if (animTarget == knifethrowanim) {
6673 weapons[i].smallrotation = 90;
6674 //weapons[i].smallrotation2=-90;
6675 weapons[i].smallrotation2 = 0;
6676 weapons[i].rotation1 = 0;
6677 weapons[i].rotation2 = 0;
6678 weapons[i].rotation3 = 0;
6680 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6681 weapons[i].smallrotation = -90;
6682 weapons[i].rotation1 = 0;
6683 weapons[i].rotation2 = 0;
6684 weapons[i].rotation3 = 0;
6687 if (weapons[i].getType() == sword) {
6688 weapons[i].smallrotation = 0;
6689 weapons[i].smallrotation2 = 0;
6690 if (animTarget == knifethrowanim) {
6691 weapons[i].smallrotation = -90;
6692 weapons[i].smallrotation2 = 0;
6693 weapons[i].rotation1 = 0;
6694 weapons[i].rotation2 = 0;
6695 weapons[i].rotation3 = 0;
6697 if ((animTarget == swordgroundstabanim && animCurrent == swordgroundstabanim) || (animTarget == swordsneakattackanim && animCurrent == swordsneakattackanim) || (animTarget == swordslashparryanim && animCurrent == swordslashparryanim) || (animTarget == swordslashparriedanim && animCurrent == swordslashparriedanim) || (animTarget == swordslashreversalanim && animCurrent == swordslashreversalanim) || (animTarget == swordslashreversedanim && animCurrent == swordslashreversedanim) || (animTarget == knifeslashreversalanim && animCurrent == knifeslashreversalanim) || (animTarget == knifeslashreversedanim && animCurrent == knifeslashreversedanim) || (animTarget == swordslashanim && animCurrent == swordslashanim) || (animTarget == drawleftanim && animCurrent == drawleftanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6698 XYZ temppoint1, temppoint2;
6701 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6702 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6703 distance = findDistance(&temppoint1, &temppoint2);
6704 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6705 weapons[i].rotation2 *= 360 / 6.28;
6708 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6709 weapons[i].rotation1 *= 360 / 6.28;
6710 weapons[i].rotation3 = 0;
6711 weapons[i].smallrotation = 90;
6712 weapons[i].smallrotation2 = 0;
6713 if (temppoint1.x > temppoint2.x)
6714 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6717 if (weapons[i].getType() == staff) {
6718 weapons[i].smallrotation = 100;
6719 weapons[i].smallrotation2 = 0;
6720 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6721 XYZ temppoint1, temppoint2;
6724 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6725 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6726 distance = findDistance(&temppoint1, &temppoint2);
6727 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6728 weapons[i].rotation2 *= 360 / 6.28;
6731 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6732 weapons[i].rotation1 *= 360 / 6.28;
6733 weapons[i].rotation3 = 0;
6734 weapons[i].smallrotation = 90;
6735 weapons[i].smallrotation2 = 0;
6736 if (temppoint1.x > temppoint2.x)
6737 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6741 if (weaponactive != k && weaponstuck != k) {
6742 if (weapons[i].getType() == knife) {
6743 weapons[i].smallrotation = -70;
6744 weapons[i].smallrotation2 = 10;
6746 if (weapons[i].getType() == sword) {
6747 weapons[i].smallrotation = -100;
6748 weapons[i].smallrotation2 = -8;
6750 if (weapons[i].getType() == staff) {
6751 weapons[i].smallrotation = -100;
6752 weapons[i].smallrotation2 = -8;
6755 if (weaponstuck == k) {
6756 if (weaponstuckwhere == 0)
6757 weapons[i].smallrotation = 180;
6759 weapons[i].smallrotation = 0;
6760 weapons[i].smallrotation2 = 10;
6769 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6771 if (animCurrent != animTarget)
6773 if (skeleton.free == 2)
6781 int Person::SphereCheck(XYZ* p1, float radius, XYZ* p, XYZ* move, float* rotate, Model* model)
6783 static float distance;
6784 static float olddistance;
6785 static int intersecting;
6786 static int firstintersecting;
6789 static XYZ start, end;
6790 static float slopethreshold = -.4;
6792 firstintersecting = -1;
6796 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6799 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6800 for (int i = 0; i < 4; i++) {
6801 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
6802 if (model->Triangles[j].facenormal.y <= slopethreshold) {
6804 distance = abs((model->Triangles[j].facenormal.x * p1->x) + (model->Triangles[j].facenormal.y * p1->y) + (model->Triangles[j].facenormal.z * p1->z) - ((model->Triangles[j].facenormal.x * model->vertex[model->Triangles[j].vertex[0]].x) + (model->Triangles[j].facenormal.y * model->vertex[model->Triangles[j].vertex[0]].y) + (model->Triangles[j].facenormal.z * model->vertex[model->Triangles[j].vertex[0]].z)));
6805 if (distance < radius) {
6806 point = *p1 - model->Triangles[j].facenormal * distance;
6807 if (PointInTriangle(&point, model->Triangles[j].facenormal, &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]]))
6810 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6811 &model->vertex[model->Triangles[j].vertex[1]],
6814 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6815 &model->vertex[model->Triangles[j].vertex[2]],
6818 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6819 &model->vertex[model->Triangles[j].vertex[2]],
6822 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
6826 if (LineFacetd(&start, &end, &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]], &model->Triangles[j].facenormal, &point)) {
6827 p1->y = point.y + radius;
6828 if ((animTarget == jumpdownanim || isFlip())) {
6829 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4))
6832 if (animTarget == jumpupanim) {
6834 animTarget = getIdle();
6841 pause_sound(whooshsound);
6842 OPENAL_SetVolume(channels[whooshsound], 0);
6845 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6848 animTarget = getLanding();
6849 emit_sound_at(landsound, coords, 128.);
6852 addEnvSound(coords);
6859 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6860 olddistance = distance;
6861 firstintersecting = j;
6866 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
6867 if (model->Triangles[j].facenormal.y > slopethreshold) {
6870 start.y -= radius / 4;
6871 XYZ& v0 = model->vertex[model->Triangles[j].vertex[0]];
6872 XYZ& v1 = model->vertex[model->Triangles[j].vertex[1]];
6873 XYZ& v2 = model->vertex[model->Triangles[j].vertex[2]];
6874 distance = abs((model->Triangles[j].facenormal.x * start.x) + (model->Triangles[j].facenormal.y * start.y) + (model->Triangles[j].facenormal.z * start.z) - ((model->Triangles[j].facenormal.x * v0.x) + (model->Triangles[j].facenormal.y * v0.y) + (model->Triangles[j].facenormal.z * v0.z)));
6875 if (distance < radius * .5) {
6876 point = start - model->Triangles[j].facenormal * distance;
6877 if (PointInTriangle(&point, model->Triangles[j].facenormal, &v0, &v1, &v2))
6880 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6882 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6884 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6886 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
6887 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6889 velocity -= DoRotation(model->Triangles[j].facenormal, 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->Triangles[j].facenormal, 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6890 if (findLengthfast(&start) < findLengthfast(&velocity))
6893 *p1 += model->Triangles[j].facenormal * (distance - radius * .5);
6896 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6897 olddistance = distance;
6898 firstintersecting = j;
6905 *p = DoRotation(*p, 0, *rotate, 0);
6908 *p1 = DoRotation(*p1, 0, *rotate, 0);
6910 return firstintersecting;
6913 int findPathDist(int start, int end)
6918 unsigned int smallestcount = 1000;
6919 for (char i = 0; i < 50; i++) {
6920 unsigned int count = 0;
6925 while (last != end && count < 30) {
6927 for (int j = 0; j < Game::numpathpoints; j++) {
6928 if (j != last && j != last2 && j != last3 && j != last4) {
6930 if (Game::numpathpointconnect[j])
6931 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
6932 if (Game::pathpointconnect[j][k] == last)
6936 if (Game::numpathpointconnect[last])
6937 for (int k = 0; k < Game::numpathpointconnect[last]; k++) {
6938 if (Game::pathpointconnect[last][k] == j)
6942 if (closest == -1 || Random() % 2 == 0) {
6953 if (count < smallestcount) {
6954 smallestcount = count;
6957 return smallestcount;
6960 void Person::takeWeapon(int weaponId)
6963 weapons[weaponId].owner = id;
6964 if (num_weapons > 0) {
6965 weaponids[num_weapons] = weaponids[0];
6968 weaponids[0] = weaponId;
6971 void Person::addClothes()
6973 if (numclothes > 0) {
6974 for (int i = 0; i < numclothes; i++) {
6981 bool Person::addClothes(const int& clothesId)
6984 const std::string fileName = clothes[clothesId];
6986 GLubyte* array = &skeleton.skinText[0];
6990 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
6995 float tintr = clothestintr[clothesId];
6996 float tintg = clothestintg[clothesId];
6997 float tintb = clothestintb[clothesId];
7013 int bytesPerPixel = texture.bpp / 8;
7017 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
7018 if (bytesPerPixel == 3)
7020 else if ((i + 1) % 4 == 0)
7021 alphanum = texture.data[i];
7022 if ((i + 1) % 4 || bytesPerPixel == 3) {
7024 texture.data[i] *= tintr;
7026 texture.data[i] *= tintg;
7028 texture.data[i] *= tintb;
7029 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
7041 if (aitype != playercontrolled && !Dialog::inDialog()) {
7043 //disable movement in editor
7044 if (Game::editorenabled)
7048 if (distsqflat(&Person::players[0]->coords, &coords) < 30 &&
7049 Person::players[0]->coords.y > coords.y + 2 &&
7050 !Person::players[0]->onterrain)
7054 if (aitype == pathfindtype) {
7055 if (finalpathfindpoint == -1) {
7056 float closestdistance;
7061 closestdistance = -1;
7062 for (int j = 0; j < Game::numpathpoints; j++) {
7063 if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) {
7064 closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]);
7066 finaltarget = Game::pathpoint[j];
7069 finalpathfindpoint = closest;
7070 for (int j = 0; j < Game::numpathpoints; j++) {
7071 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7072 DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7073 if (sq(tempdist) < closestdistance)
7074 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7075 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7076 closestdistance = sq(tempdist);
7078 finaltarget = colpoint;
7082 finalpathfindpoint = closest;
7084 if (targetpathfindpoint == -1) {
7085 float closestdistance;
7090 closestdistance = -1;
7091 if (lastpathfindpoint == -1) {
7092 for (int j = 0; j < Game::numpathpoints; j++) {
7093 if (j != lastpathfindpoint)
7094 if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) {
7095 closestdistance = distsq(&coords, &Game::pathpoint[j]);
7099 targetpathfindpoint = closest;
7100 for (int j = 0; j < Game::numpathpoints; j++)
7101 if (j != lastpathfindpoint)
7102 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7103 DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7104 if (sq(tempdist) < closestdistance) {
7105 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7106 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7107 closestdistance = sq(tempdist);
7112 targetpathfindpoint = closest;
7114 for (int j = 0; j < Game::numpathpoints; j++)
7115 if (j != lastpathfindpoint &&
7116 j != lastpathfindpoint2 &&
7117 j != lastpathfindpoint3 &&
7118 j != lastpathfindpoint4) {
7120 if (Game::numpathpointconnect[j])
7121 for (int k = 0; k < Game::numpathpointconnect[j]; k++)
7122 if (Game::pathpointconnect[j][k] == lastpathfindpoint)
7125 if (Game::numpathpointconnect[lastpathfindpoint])
7126 for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++)
7127 if (Game::pathpointconnect[lastpathfindpoint][k] == j)
7130 tempdist = findPathDist(j, finalpathfindpoint);
7131 if (closest == -1 || tempdist < closestdistance) {
7132 closestdistance = tempdist;
7137 targetpathfindpoint = closest;
7140 losupdatedelay -= multiplier;
7142 targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]);
7143 lookyaw = targetyaw;
7145 //reached target point
7146 if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) {
7147 lastpathfindpoint4 = lastpathfindpoint3;
7148 lastpathfindpoint3 = lastpathfindpoint2;
7149 lastpathfindpoint2 = lastpathfindpoint;
7150 lastpathfindpoint = targetpathfindpoint;
7151 if (lastpathfindpoint2 == -1)
7152 lastpathfindpoint2 = lastpathfindpoint;
7153 if (lastpathfindpoint3 == -1)
7154 lastpathfindpoint3 = lastpathfindpoint2;
7155 if (lastpathfindpoint4 == -1)
7156 lastpathfindpoint4 = lastpathfindpoint3;
7157 targetpathfindpoint = -1;
7159 if (distsqflat(&coords, &finalfinaltarget) <
7160 distsqflat(&coords, &finaltarget) ||
7161 distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) ||
7162 lastpathfindpoint == finalpathfindpoint) {
7163 aitype = passivetype;
7174 if (avoidcollided > .8 && !jumpkeydown && collided < .8)
7175 targetyaw += 90 * (whichdirection * 2 - 1);
7177 if (collided < 1 || animTarget != jumpupanim)
7179 if ((collided > .8 && jumppower >= 5))
7182 if ((!Tutorial::active || cananger) &&
7184 !Person::players[0]->dead &&
7185 distsq(&coords, &Person::players[0]->coords) < 400 &&
7187 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7188 Animation::animations[Person::players[0]->animTarget].height != lowheight &&
7189 !Game::editorenabled &&
7190 (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain))
7191 aitype = attacktypecutoff;
7192 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7193 Animation::animations[Person::players[0]->animTarget].height == highheight &&
7194 !Game::editorenabled)
7195 aitype = attacktypecutoff;
7197 if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7198 losupdatedelay = .2;
7199 for (unsigned j = 0; j < Person::players.size(); j++)
7200 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype)
7201 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
7202 if (distsq(&coords, &Person::players[j]->coords) < 400)
7203 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0)
7204 if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain)
7205 if (!Person::players[j]->isWallJump() && -1 == Object::checkcollide(DoRotation(jointPos(head), 0, yaw, 0) * scale + coords, DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0) * Person::players[j]->scale + Person::players[j]->coords) ||
7206 (Person::players[j]->animTarget == hanganim &&
7207 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7208 aitype = searchtype;
7210 lastseen = Person::players[j]->coords;
7215 if (aitype == attacktypecutoff && Game::musictype != 2)
7216 if (creature != wolftype) {
7222 if (aitype != passivetype && Game::leveltime > .5)
7223 howactive = typeactive;
7225 if (aitype == passivetype) {
7226 aiupdatedelay -= multiplier;
7227 losupdatedelay -= multiplier;
7228 lastseentime += multiplier;
7229 pausetime -= multiplier;
7230 if (lastseentime > 1)
7233 if (aiupdatedelay < 0) {
7234 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7235 targetyaw = roughDirectionTo(coords, waypoints[waypoint]);
7236 lookyaw = targetyaw;
7237 aiupdatedelay = .05;
7239 if (distsqflat(&coords, &waypoints[waypoint]) < 1) {
7240 if (waypointtype[waypoint] == wppause)
7243 if (waypoint > numwaypoints - 1)
7248 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0)
7259 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7260 if (!avoidsomething)
7261 targetyaw += 90 * (whichdirection * 2 - 1);
7263 XYZ leftpos, rightpos;
7264 float leftdist, rightdist;
7265 leftpos = coords + DoRotation(facing, 0, 90, 0);
7266 rightpos = coords - DoRotation(facing, 0, 90, 0);
7267 leftdist = distsq(&leftpos, &avoidwhere);
7268 rightdist = distsq(&rightpos, &avoidwhere);
7269 if (leftdist < rightdist)
7276 if (collided < 1 || animTarget != jumpupanim)
7278 if ((collided > .8 && jumppower >= 5))
7282 if (!Game::editorenabled) {
7283 if (howactive <= typesleeping)
7284 if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile)
7285 for (int j = 0; j < numenvsounds; j++) {
7286 float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
7287 if (vol > 0 && distsq(&coords, &envsound[j]) < 2 * (vol + vol * (creature == rabbittype) * 3))
7288 aitype = attacktypecutoff;
7291 if (aitype != passivetype) {
7292 if (howactive == typesleeping)
7293 setTargetAnimation(getupfromfrontanim);
7294 howactive = typeactive;
7298 if (howactive < typesleeping &&
7299 ((!Tutorial::active || cananger) && hostile) &&
7300 !Person::players[0]->dead &&
7301 distsq(&coords, &Person::players[0]->coords) < 400 &&
7303 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7304 Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled)
7305 aitype = attacktypecutoff;
7306 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7307 Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled)
7308 aitype = attacktypecutoff;
7311 if (creature == wolftype) {
7313 for (unsigned j = 0; j < Person::players.size(); j++) {
7314 if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
7315 float smelldistance = 50;
7316 if (j == 0 && Person::players[j]->num_weapons > 0) {
7317 if (weapons[Person::players[j]->weaponids[0]].bloody)
7318 smelldistance = 100;
7319 if (Person::players[j]->num_weapons == 2)
7320 if (weapons[Person::players[j]->weaponids[1]].bloody)
7321 smelldistance = 100;
7324 smelldistance = 100;
7325 windsmell = windvector;
7326 Normalise(&windsmell);
7327 windsmell = windsmell * 2 + Person::players[j]->coords;
7328 if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled)
7329 aitype = attacktypecutoff;
7334 if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7335 losupdatedelay = .2;
7336 for (unsigned j = 0; j < Person::players.size(); j++) {
7337 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7338 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
7339 if (distsq(&coords, &Person::players[j]->coords) < 400)
7340 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0)
7341 if ((-1 == Object::checkcollide(
7342 DoRotation(jointPos(head), 0, yaw, 0) *
7345 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0) *
7346 Person::players[j]->scale +
7347 Person::players[j]->coords) &&
7348 !Person::players[j]->isWallJump()) ||
7349 (Person::players[j]->animTarget == hanganim &&
7350 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7352 if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight)
7357 if (lastseentime <= 0) {
7358 aitype = searchtype;
7360 lastseen = Person::players[j]->coords;
7368 if (aitype == attacktypecutoff && Game::musictype != 2) {
7369 if (creature != wolftype) {
7373 if (creature == wolftype) {
7383 if (aitype == searchtype) {
7384 aiupdatedelay -= multiplier;
7385 losupdatedelay -= multiplier;
7387 lastseentime -= multiplier;
7388 lastchecktime -= multiplier;
7390 if (isRun() && !onground) {
7391 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7392 XYZ test2 = coords + facing;
7394 XYZ test = coords + facing;
7396 j = Object::checkcollide(test2, test, laststanding);
7398 j = Object::checkcollide(test2, test);
7401 setTargetAnimation(getStop());
7404 //aitype=passivetype;
7405 aitype = pathfindtype;
7406 finalfinaltarget = waypoints[waypoint];
7407 finalpathfindpoint = -1;
7408 targetpathfindpoint = -1;
7409 lastpathfindpoint = -1;
7410 lastpathfindpoint2 = -1;
7411 lastpathfindpoint3 = -1;
7412 lastpathfindpoint4 = -1;
7417 //check out last seen location
7418 if (aiupdatedelay < 0) {
7419 targetyaw = roughDirectionTo(coords, lastseen);
7420 lookyaw = targetyaw;
7421 aiupdatedelay = .05;
7424 if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) {
7427 lastseen.x += (float(Random() % 100) - 50) / 25;
7428 lastseen.z += (float(Random() % 100) - 50) / 25;
7439 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7440 if (!avoidsomething)
7441 targetyaw += 90 * (whichdirection * 2 - 1);
7443 XYZ leftpos, rightpos;
7444 float leftdist, rightdist;
7445 leftpos = coords + DoRotation(facing, 0, 90, 0);
7446 rightpos = coords - DoRotation(facing, 0, 90, 0);
7447 leftdist = distsq(&leftpos, &avoidwhere);
7448 rightdist = distsq(&rightpos, &avoidwhere);
7449 if (leftdist < rightdist)
7456 if (collided < 1 || animTarget != jumpupanim)
7458 if ((collided > .8 && jumppower >= 5))
7461 if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile))
7462 for (int k = 0; k < numenvsounds; k++) {
7463 if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) {
7464 aitype = attacktypecutoff;
7468 if (!Person::players[0]->dead &&
7469 losupdatedelay < 0 &&
7470 !Game::editorenabled &&
7472 ((!Tutorial::active || cananger) && hostile)) {
7473 losupdatedelay = .2;
7474 if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) {
7475 aitype = attacktypecutoff;
7478 if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight)
7479 //TODO: factor out canSeePlayer()
7480 if (distsq(&coords, &Person::players[0]->coords) < 400)
7481 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0)
7482 if ((Object::checkcollide(
7483 DoRotation(jointPos(head), 0, yaw, 0) *
7486 DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0) *
7487 Person::players[0]->scale +
7488 Person::players[0]->coords) == -1) ||
7489 (Person::players[0]->animTarget == hanganim && normaldotproduct(Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) {
7490 /* //TODO: changed j to 0 on a whim, make sure this is correct
7491 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
7492 Person::players[j]->facing,coords-Person::players[j]->coords)<0)
7494 aitype = attacktypecutoff;
7499 if (lastseentime < 0) {
7500 //aitype=passivetype;
7502 aitype = pathfindtype;
7503 finalfinaltarget = waypoints[waypoint];
7504 finalpathfindpoint = -1;
7505 targetpathfindpoint = -1;
7506 lastpathfindpoint = -1;
7507 lastpathfindpoint2 = -1;
7508 lastpathfindpoint3 = -1;
7509 lastpathfindpoint4 = -1;
7513 if (aitype != gethelptype)
7516 //get help from buddies
7517 if (aitype == gethelptype) {
7518 runninghowlong += multiplier;
7519 aiupdatedelay -= multiplier;
7521 if (aiupdatedelay < 0 || ally == 0) {
7525 //TODO: factor out closest search somehow
7528 float closestdist = -1;
7529 for (unsigned k = 0; k < Person::players.size(); k++) {
7530 if ((k != id) && (k != 0) && !Person::players[k]->dead &&
7531 (Person::players[k]->howactive < typedead1) &&
7532 !Person::players[k]->skeleton.free &&
7533 (Person::players[k]->aitype == passivetype)) {
7534 float distance = distsq(&coords, &Person::players[k]->coords);
7535 if (closestdist == -1 || distance < closestdist) {
7536 closestdist = distance;
7542 if (closest != -1) {
7547 lastseen = Person::players[0]->coords;
7553 XYZ facing = coords;
7554 XYZ flatfacing = Person::players[ally]->coords;
7555 facing.y += jointPos(head).y * scale;
7556 flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale;
7557 if (-1 != Object::checkcollide(facing, flatfacing))
7560 //no available ally, run back to player
7562 Person::players[ally]->skeleton.free ||
7563 Person::players[ally]->aitype != passivetype ||
7564 lastseentime <= 0) {
7565 aitype = searchtype;
7571 targetyaw = roughDirectionTo(coords, Person::players[ally]->coords);
7572 lookyaw = targetyaw;
7573 aiupdatedelay = .05;
7576 if (distsqflat(&coords, &Person::players[ally]->coords) < 3) {
7577 aitype = searchtype;
7579 Person::players[ally]->aitype = searchtype;
7580 if (Person::players[ally]->lastseentime < lastseentime) {
7581 Person::players[ally]->lastseen = lastseen;
7582 Person::players[ally]->lastseentime = lastseentime;
7583 Person::players[ally]->lastchecktime = lastchecktime;
7587 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7588 if (!avoidsomething)
7589 targetyaw += 90 * (whichdirection * 2 - 1);
7591 XYZ leftpos, rightpos;
7592 float leftdist, rightdist;
7593 leftpos = coords + DoRotation(facing, 0, 90, 0);
7594 rightpos = coords - DoRotation(facing, 0, 90, 0);
7595 leftdist = distsq(&leftpos, &avoidwhere);
7596 rightdist = distsq(&rightpos, &avoidwhere);
7597 if (leftdist < rightdist)
7611 if (collided < 1 || animTarget != jumpupanim)
7613 if (collided > .8 && jumppower >= 5)
7617 //retreiving a weapon on the ground
7618 if (aitype == getweapontype) {
7619 aiupdatedelay -= multiplier;
7620 lastchecktime -= multiplier;
7622 if (aiupdatedelay < 0) {
7628 float closestdist = -1;
7629 for (unsigned k = 0; k < weapons.size(); k++)
7630 if (weapons[k].owner == -1) {
7631 float distance = distsq(&coords, &weapons[k].position);
7632 if (closestdist == -1 || distance < closestdist) {
7633 closestdist = distance;
7646 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile))
7647 if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) {
7648 aitype = attacktypecutoff;
7651 if (!Person::players[0]->dead)
7653 if (weapons[ally].owner != -1 ||
7654 distsq(&coords, &weapons[ally].position) > 16) {
7655 aitype = attacktypecutoff;
7658 //TODO: factor these out as moveToward()
7659 targetyaw = roughDirectionTo(coords, weapons[ally].position);
7660 lookyaw = targetyaw;
7661 aiupdatedelay = .05;
7664 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7665 if (!avoidsomething)
7666 targetyaw += 90 * (whichdirection * 2 - 1);
7668 XYZ leftpos, rightpos;
7669 float leftdist, rightdist;
7670 leftpos = coords + DoRotation(facing, 0, 90, 0);
7671 rightpos = coords - DoRotation(facing, 0, 90, 0);
7672 leftdist = distsq(&leftpos, &avoidwhere);
7673 rightdist = distsq(&rightpos, &avoidwhere);
7674 if (leftdist < rightdist)
7688 if (animTarget != crouchremoveknifeanim &&
7689 animTarget != removeknifeanim)
7690 throwtogglekeydown = 0;
7693 if (collided < 1 || animTarget != jumpupanim)
7695 if ((collided > .8 && jumppower >= 5))
7699 if (aitype == attacktypecutoff) {
7700 aiupdatedelay -= multiplier;
7701 //dodge or reverse rabbit kicks, knife throws, flips
7702 if (damage < damagetolerance * 2 / 3)
7703 if ((Person::players[0]->animTarget == rabbitkickanim ||
7704 Person::players[0]->animTarget == knifethrowanim ||
7705 (Person::players[0]->isFlip() &&
7706 normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) &&
7707 !Person::players[0]->skeleton.free &&
7708 (aiupdatedelay < .1)) {
7712 if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
7713 if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
7714 if (isIdle() || isCrouch() || isRun() || isFlip()) {
7715 if (abs(Random() % 2) == 0) {
7716 setTargetAnimation(backhandspringanim);
7718 setTargetAnimation(rollanim);
7720 targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
7723 if (animTarget == jumpupanim || animTarget == jumpdownanim) {
7724 setTargetAnimation(flipanim);
7729 aiupdatedelay = .02;
7731 //get confused by flips
7732 if (Person::players[0]->isFlip() &&
7733 !Person::players[0]->skeleton.free &&
7734 Person::players[0]->animTarget != walljumprightkickanim &&
7735 Person::players[0]->animTarget != walljumpleftkickanim) {
7736 if (distsq(&Person::players[0]->coords, &coords) < 25)
7737 if ((1 - damage / damagetolerance) > .5)
7740 //go for weapon on the ground
7741 if (wentforweapon < 3)
7742 for (unsigned k = 0; k < weapons.size(); k++)
7743 if (creature != wolftype)
7744 if (num_weapons == 0 &&
7745 weapons[k].owner == -1 &&
7746 weapons[k].velocity.x == 0 &&
7747 weapons[k].velocity.z == 0 &&
7748 weapons[k].velocity.y == 0) {
7749 if (distsq(&coords, &weapons[k].position) < 16) {
7752 aitype = getweapontype;
7756 //dodge/reverse walljump kicks
7757 if (damage < damagetolerance / 2)
7758 if (Animation::animations[animTarget].height != highheight)
7759 if (damage < damagetolerance * .5 &&
7760 ((Person::players[0]->animTarget == walljumprightkickanim ||
7761 Person::players[0]->animTarget == walljumpleftkickanim) &&
7762 ((aiupdatedelay < .15 &&
7764 (aiupdatedelay < .08 &&
7765 difficulty != 2)))) {
7768 //walked off a ledge (?)
7769 if (isRun() && !onground)
7770 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7771 XYZ test2 = coords + facing;
7773 XYZ test = coords + facing;
7775 j = Object::checkcollide(test2, test, laststanding);
7777 j = Object::checkcollide(test2, test);
7780 setTargetAnimation(getStop());
7783 aitype = pathfindtype;
7784 finalfinaltarget = waypoints[waypoint];
7785 finalpathfindpoint = -1;
7786 targetpathfindpoint = -1;
7787 lastpathfindpoint = -1;
7788 lastpathfindpoint2 = -1;
7789 lastpathfindpoint3 = -1;
7790 lastpathfindpoint4 = -1;
7794 //lose sight of player in the air (?)
7795 if (Person::players[0]->coords.y > coords.y + 5 &&
7796 Animation::animations[Person::players[0]->animTarget].height != highheight &&
7797 !Person::players[0]->onterrain) {
7798 aitype = pathfindtype;
7799 finalfinaltarget = waypoints[waypoint];
7800 finalpathfindpoint = -1;
7801 targetpathfindpoint = -1;
7802 lastpathfindpoint = -1;
7803 lastpathfindpoint2 = -1;
7804 lastpathfindpoint3 = -1;
7805 lastpathfindpoint4 = -1;
7807 //it's time to think (?)
7808 if (aiupdatedelay < 0 &&
7809 !Animation::animations[animTarget].attack &&
7810 animTarget != staggerbackhighanim &&
7811 animTarget != staggerbackhardanim &&
7812 animTarget != backhandspringanim &&
7813 animTarget != dodgebackanim) {
7815 if (weaponactive == -1 && num_weapons > 0)
7816 drawkeydown = Random() % 2;
7819 rabbitkickenabled = Random() % 2;
7821 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
7822 XYZ targetpoint = Person::players[0]->coords;
7823 if (distsq(&Person::players[0]->coords, &coords) <
7824 distsq(&rotatetarget, &coords))
7825 targetpoint += Person::players[0]->velocity *
7826 findDistance(&Person::players[0]->coords, &coords) / findLength(&velocity);
7827 targetyaw = roughDirectionTo(coords, targetpoint);
7828 lookyaw = targetyaw;
7829 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
7831 if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1))
7833 else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
7834 distsq(&coords, &Person::players[0]->coords) < 9) &&
7835 Person::players[0]->weaponactive != -1)
7837 else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0))
7841 //chill out around the corpse
7842 if (Person::players[0]->dead) {
7844 if (Random() % 10 == 0)
7846 if (Random() % 100 == 0) {
7847 aitype = pathfindtype;
7848 finalfinaltarget = waypoints[waypoint];
7849 finalpathfindpoint = -1;
7850 targetpathfindpoint = -1;
7851 lastpathfindpoint = -1;
7852 lastpathfindpoint2 = -1;
7853 lastpathfindpoint3 = -1;
7854 lastpathfindpoint4 = -1;
7863 if (avoidcollided > .8 && !jumpkeydown && collided < .8)
7864 targetyaw += 90 * (whichdirection * 2 - 1);
7866 if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype)
7870 if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7)
7874 if (aitype != playercontrolled &&
7879 for (unsigned j = 0; j < Person::players.size(); j++)
7880 if (j != id && !Person::players[j]->skeleton.free &&
7881 Person::players[j]->hasvictim &&
7882 (Tutorial::active && reversaltrain ||
7883 Random() % 2 == 0 && difficulty == 2 ||
7884 Random() % 4 == 0 && difficulty == 1 ||
7885 Random() % 8 == 0 && difficulty == 0 ||
7886 Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
7887 Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
7888 (Random() % 2 == 0 || difficulty == 2) ||
7889 (isIdle() || isRun()) &&
7890 Person::players[j]->weaponactive != -1 ||
7891 Person::players[j]->animTarget == swordslashanim &&
7892 weaponactive != -1 ||
7893 Person::players[j]->animTarget == staffhitanim ||
7894 Person::players[j]->animTarget == staffspinhitanim))
7895 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
7896 Person::players[j]->victim == Person::players[id] &&
7897 (Person::players[j]->animTarget == sweepanim ||
7898 Person::players[j]->animTarget == spinkickanim ||
7899 Person::players[j]->animTarget == staffhitanim ||
7900 Person::players[j]->animTarget == staffspinhitanim ||
7901 Person::players[j]->animTarget == winduppunchanim ||
7902 Person::players[j]->animTarget == upunchanim ||
7903 Person::players[j]->animTarget == wolfslapanim ||
7904 Person::players[j]->animTarget == knifeslashstartanim ||
7905 Person::players[j]->animTarget == swordslashanim &&
7906 (distsq(&Person::players[j]->coords, &coords) < 2 ||
7907 weaponactive != -1))) {
7915 Person::players[target]->Reverse();
7920 if (collided > .8 && jumppower >= 5 ||
7921 distsq(&coords, &Person::players[0]->coords) > 400 &&
7923 creature == rabbittype)
7925 //TODO: why are we controlling the human?
7926 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0)
7927 Person::players[0]->jumpkeydown = 0;
7928 if (Person::players[0]->animTarget == jumpdownanim &&
7929 distsq(&Person::players[0]->coords, &coords) < 40)
7934 if (Tutorial::active)
7938 XYZ facing = coords;
7939 XYZ flatfacing = Person::players[0]->coords;
7940 facing.y += jointPos(head).y * scale;
7941 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
7943 if (-1 != Object::checkcollide(facing, flatfacing)) {
7946 if (lastseentime <= 0 &&
7947 (creature != wolftype ||
7948 weaponstuck == -1)) {
7949 aitype = searchtype;
7951 lastseen = Person::players[0]->coords;
7958 if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
7959 (aitype == attacktypecutoff ||
7960 aitype == searchtype))
7961 if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
7962 XYZ test = Person::players[0]->coords;
7964 if (-1 == Object::checkcollide(Person::players[0]->coords, test))
7968 if (aitype == passivetype && !(numwaypoints > 1) ||
7970 pause && damage > superpermanentdamage) {
7988 XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0);
7989 facing = flatfacing;
7991 if (aitype == attacktypecutoff) {
7992 targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
7993 targetheadpitch = pitchTo(coords, Person::players[0]->coords);
7994 } else if (howactive >= typesleeping) {
7995 targetheadyaw = targetyaw;
7996 targetheadpitch = 0;
7998 if (interestdelay <= 0) {
7999 interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
8000 headtarget = coords;
8001 headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
8002 headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
8003 headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
8004 headtarget += facing * 1.5;
8006 targetheadyaw = 180 - roughDirectionTo(coords, headtarget);
8007 targetheadpitch = pitchTo(coords, headtarget);