2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2017 - 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]);
460 clothes[k][templength] = '\0';
461 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
467 if (creature == wolftype) {
469 damagetolerance = 300;
476 realoldcoords = coords;
479 void Person::skeletonLoad(bool clothes)
482 if (creature != wolftype) {
484 "Skeleton/BasicFigure",
485 "Skeleton/BasicFigureLow",
486 "Skeleton/RabbitBelt",
488 "Models/Body2.solid",
489 "Models/Body3.solid",
490 "Models/Body4.solid",
491 "Models/Body5.solid",
492 "Models/Body6.solid",
493 "Models/Body7.solid",
494 "Models/BodyLow.solid",
499 "Skeleton/BasicFigureWolf",
500 "Skeleton/BasicFigureWolfLow",
501 "Skeleton/RabbitBelt",
503 "Models/Wolf2.solid",
504 "Models/Wolf3.solid",
505 "Models/Wolf4.solid",
506 "Models/Wolf5.solid",
507 "Models/Wolf6.solid",
508 "Models/Wolf7.solid",
509 "Models/WolfLow.solid",
514 skeleton.drawmodel.textureptr.load(creatureskin[creature][whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
520 * GameTick/doPlayerCollisions
522 void Person::CheckKick()
524 if (!(hasvictim && (animTarget == rabbitkickanim && victim && victim != this->shared_from_this() && frameCurrent >= 2 && animCurrent == rabbitkickanim) && distsq(&coords, &victim->coords) < 1.2 && !victim->skeleton.free)) {
528 if (Animation::animations[victim->animTarget].height != lowheight) {
529 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
530 XYZ relative = velocity;
532 Normalise(&relative);
536 if (!Tutorial::active) {
537 emit_sound_at(heavyimpactsound, victim->coords);
540 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
541 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
544 victim->DoDamage(100 * damagemult / victim->protectionhigh);
551 animTarget = backflipanim;
553 velocity = facing * -10;
557 resume_stream(whooshsound);
560 award_bonus(id, cannon);
561 } else if (victim->isCrouch()) {
562 animTarget = rabbitkickreversedanim;
563 animCurrent = rabbitkickreversedanim;
564 victim->animCurrent = rabbitkickreversalanim;
565 victim->animTarget = rabbitkickreversalanim;
571 victim->oldcoords = victim->coords;
572 coords = victim->coords;
573 victim->targetyaw = targetyaw;
574 victim->victim = this->shared_from_this();
581 * GameTick::doPlayerCollisions - spread fire between players
582 * GameTick::ProcessDevKeys - press f to ignite
583 * Person::DoStuff - spread fire from lit campfires and bushes
585 void Person::CatchFire()
587 XYZ flatfacing, flatvelocity;
589 for (int i = 0; i < 10; i++) {
590 howmany = fabs(Random() % (skeleton.joints.size()));
592 flatvelocity = skeleton.joints[howmany].velocity;
593 flatfacing = skeleton.joints[howmany].position * scale + coords;
595 flatvelocity = velocity;
596 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
598 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
603 emit_sound_at(firestartsound, coords);
605 emit_stream_at(stream_firesound, coords);
613 * idle animation for this creature (depending on status)
615 int Person::getIdle()
617 if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype)) {
620 if (hasvictim && (victim != this->shared_from_this())) {
621 if ((!victim->dead && victim->aitype != passivetype &&
622 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
623 victim->id < Person::players.size())) {
624 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
625 if (creature == rabbittype) {
626 return fightidleanim;
628 if (creature == wolftype) {
632 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
633 if (weapons[weaponids[weaponactive]].getType() == knife) {
634 return knifefightidleanim;
636 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1) {
637 return swordfightidlebothanim;
639 if (weapons[weaponids[weaponactive]].getType() == sword) {
640 return swordfightidleanim;
642 if (weapons[weaponids[weaponactive]].getType() == staff) {
643 return swordfightidleanim;
646 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause) {
647 return fightsidestep;
651 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype) {
654 if (howactive == typesitting) {
657 if (howactive == typesittingwall) {
660 if (howactive == typesleeping) {
663 if (howactive == typedead1) {
666 if (howactive == typedead2) {
669 if (howactive == typedead3) {
672 if (howactive == typedead4) {
675 if (creature == rabbittype) {
676 return bounceidleanim;
678 if (creature == wolftype) {
685 * crouch animation for this creature
687 int Person::getCrouch()
689 if (creature == rabbittype) {
692 if (creature == wolftype) {
693 return wolfcrouchanim;
699 * running animation for this creature (can be upright or all fours)
703 if (creature == rabbittype && (!superruntoggle || weaponactive != -1)) {
706 if (creature == wolftype && (!superruntoggle)) {
710 if (creature == rabbittype && (superruntoggle && weaponactive == -1)) {
711 return rabbitrunninganim;
713 if (creature == wolftype && (superruntoggle)) {
714 return wolfrunninganim;
721 int Person::getStop()
723 if (creature == rabbittype) {
726 if (creature == wolftype) {
734 int Person::getLanding()
736 if (creature == rabbittype) {
739 if (creature == wolftype) {
747 int Person::getLandhard()
749 if (creature == rabbittype) {
752 if (creature == wolftype) {
753 return wolflandhardanim;
761 * Person::DoAnimations
764 SolidHitBonus(int playerid)
766 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo) {
767 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
769 award_bonus(playerid, solidhit);
774 * spawns blood effects
776 void Person::DoBlood(float howmuch, int which)
778 // FIXME: should abstract out inputs
779 static int bleedxint, bleedyint;
781 if (bloodtoggle && !Tutorial::active) {
782 if (bleeding <= 0 && spurt) {
784 for (int i = 0; i < 3; i++) {
785 // emit blood particles
788 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
789 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
790 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
791 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
794 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
795 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
796 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
797 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
800 if (Random() % 2 == 0) { // 50% chance
801 for (int i = 0; i < 3; i++) {
802 if (Random() % 2 != 0) {
803 // emit teeth particles
806 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
807 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
810 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
811 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
815 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
817 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
819 Sprite::setLastSpriteSpecial(3); // sets it to teeth
825 // FIXME: manipulating attributes
826 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
829 if (creature == rabbittype) {
830 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) {
831 bleedxint = abs(Random() % 512);
832 bleedyint = abs(Random() % 512);
835 if (creature == wolftype) {
836 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) {
837 bleedxint = abs(Random() % 512);
838 bleedyint = abs(Random() % 512);
843 bleedy /= realtexdetail;
844 bleedx /= realtexdetail;
845 direction = abs(Random() % 2) * 2 - 1;
854 * spawns big blood effects and ???
855 * modifies character's skin texture
857 void Person::DoBloodBig(float howmuch, int which)
859 static int bleedxint, bleedyint, i, j;
861 if (howmuch && id == 0) {
865 if (!Tutorial::active || id == 0) {
866 if (aitype != playercontrolled && howmuch > 0) {
870 if (creature == wolftype) {
871 int i = abs(Random() % 2);
873 whichsound = snarlsound;
876 whichsound = snarl2sound;
879 if (creature == rabbittype) {
880 int i = abs(Random() % 2);
882 whichsound = rabbitpainsound;
884 if (i == 1 && howmuch >= 2) {
885 whichsound = rabbitpain1sound;
889 if (whichsound != -1) {
890 emit_sound_at(whichsound, coords);
896 if (id == 0 && howmuch > 0) {
900 if (bloodtoggle && decalstoggle && !Tutorial::active) {
901 if (bleeding <= 0 && spurt) {
903 for (int i = 0; i < 3; i++) {
904 // emit blood particles
905 // FIXME: copypaste from above
908 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
909 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
910 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
911 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
914 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
915 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
916 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
917 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
922 // weird texture manipulation code follows.
923 // looks like this is painting blood onto the character's skin texture
924 // FIXME: surely there's a better way
926 int offsetx = 0, offsety = 0;
928 offsety = Random() % 40;
929 offsetx = abs(Random() % 60);
931 if (which == 190 || which == 185) {
932 offsety = Random() % 40;
933 offsetx = abs(Random() % 100) - 20;
936 offsety = Random() % 10;
937 offsetx = Random() % 10;
940 offsety = Random() % 20;
941 offsetx = Random() % 20;
943 if (which == 220 || which == 215) {
952 if (creature == rabbittype) {
953 for (i = 0; i < 512; i++) {
954 for (j = 0; j < 512; j++) {
955 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
972 if (creature == wolftype) {
973 for (i = 0; i < 512; i++) {
974 for (j = 0; j < 512; j++) {
975 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1004 if (endx > 512 - 1) {
1007 if (endy > 512 - 1) {
1010 if (endx < startx) {
1013 if (endy < starty) {
1017 startx /= realtexdetail;
1018 starty /= realtexdetail;
1019 endx /= realtexdetail;
1020 endy /= realtexdetail;
1022 int texdetailint = realtexdetail;
1024 if (creature == rabbittype) {
1025 for (i = startx; i < endx; i++) {
1026 for (j = starty; j < endy; j++) {
1027 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) {
1028 color = Random() % 85 + 170;
1029 where = i * skeleton.skinsize * 3 + j * 3;
1030 if (skeleton.skinText[where + 0] > color / 2) {
1031 skeleton.skinText[where + 0] = color / 2;
1033 skeleton.skinText[where + 1] = 0;
1034 skeleton.skinText[where + 2] = 0;
1039 if (creature == wolftype) {
1040 for (i = startx; i < endx; i++) {
1041 for (j = starty; j < endy; j++) {
1042 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) {
1043 color = Random() % 85 + 170;
1044 where = i * skeleton.skinsize * 3 + j * 3;
1045 if (skeleton.skinText[where + 0] > color / 2) {
1046 skeleton.skinText[where + 0] = color / 2;
1048 skeleton.skinText[where + 1] = 0;
1049 skeleton.skinText[where + 2] = 0;
1054 skeleton.drawmodel.textureptr.bind();
1059 if (creature == rabbittype) {
1060 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) {
1061 bleedxint = abs(Random() % 512);
1062 bleedyint = abs(Random() % 512);
1065 if (creature == wolftype) {
1066 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) {
1067 bleedxint = abs(Random() % 512);
1068 bleedyint = abs(Random() % 512);
1071 bleedy = bleedxint + offsetx;
1072 bleedx = bleedyint + offsety;
1073 bleedy /= realtexdetail;
1074 bleedx /= realtexdetail;
1081 if (bleedx > skeleton.skinsize - 1) {
1082 bleedx = skeleton.skinsize - 1;
1084 if (bleedy > skeleton.skinsize - 1) {
1085 bleedy = skeleton.skinsize - 1;
1087 direction = abs(Random() % 2) * 2 - 1;
1089 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1090 deathbleeding += bleeding;
1091 bloodloss += bleeding * 3;
1093 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1094 if (abs(Random() % 2) == 0) {
1095 aitype = gethelptype;
1098 aitype = attacktypecutoff;
1108 * similar to DoBloodBig
1110 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
1113 static XYZ bloodvel;
1114 static XYZ startpoint, endpoint, colpoint, movepoint;
1115 static float rotationpoint;
1116 static int whichtri;
1117 static XYZ p1, p2, p3, p0;
1120 float coordsx, coordsy;
1123 if (bloodtoggle && decalstoggle && !Tutorial::active) {
1125 if (!skeleton.free) {
1126 where = DoRotation(where, 0, -yaw, 0);
1130 startpoint.y += 100;
1135 // ray testing for a tri in the character model
1136 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
1137 if (whichtri != -1) {
1138 // low level geometry math
1140 p1 = skeleton.drawmodel.getTriangleVertex(whichtri, 0);
1141 p2 = skeleton.drawmodel.getTriangleVertex(whichtri, 1);
1142 p3 = skeleton.drawmodel.getTriangleVertex(whichtri, 2);
1144 bary.x = distsq(&p0, &p1);
1145 bary.y = distsq(&p0, &p2);
1146 bary.z = distsq(&p0, &p3);
1148 total = bary.x + bary.y + bary.z;
1153 bary.x = 1 - bary.x;
1154 bary.y = 1 - bary.y;
1155 bary.z = 1 - bary.z;
1157 total = bary.x + bary.y + bary.z;
1162 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1163 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1164 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1165 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1166 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1167 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1168 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;
1169 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;
1171 if (bleeding <= 0 && spurt) {
1173 for (int i = 0; i < 3; i++) {
1174 // emit blood particles
1175 // FIXME: more copypaste code
1177 if (skeleton.free) {
1178 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1179 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1180 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1181 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1184 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1185 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1186 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1187 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1192 // texture manipulation follows
1194 int offsetx = 0, offsety = 0;
1195 offsetx = (1 + coordsy) * 512 - 291;
1196 offsety = coordsx * 512 - 437;
1203 if (creature == rabbittype) {
1204 for (i = 0; i < 512; i++) {
1205 for (j = 0; j < 512; j++) {
1206 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1223 if (creature == wolftype) {
1224 for (i = 0; i < 512; i++) {
1225 for (j = 0; j < 512; j++) {
1226 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1254 if (endx > 512 - 1) {
1257 if (endy > 512 - 1) {
1260 if (endx < startx) {
1263 if (endy < starty) {
1267 startx /= realtexdetail;
1268 starty /= realtexdetail;
1269 endx /= realtexdetail;
1270 endy /= realtexdetail;
1272 int texdetailint = realtexdetail;
1274 if (creature == rabbittype) {
1275 for (i = startx; i < endx; i++) {
1276 for (j = starty; j < endy; j++) {
1277 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) {
1278 color = Random() % 85 + 170;
1279 where = i * skeleton.skinsize * 3 + j * 3;
1280 if (skeleton.skinText[where + 0] > color / 2) {
1281 skeleton.skinText[where + 0] = color / 2;
1283 skeleton.skinText[where + 1] = 0;
1284 skeleton.skinText[where + 2] = 0;
1285 } 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) {
1286 color = Random() % 85 + 170;
1287 where = i * skeleton.skinsize * 3 + j * 3;
1288 if (skeleton.skinText[where + 0] > color / 2) {
1289 skeleton.skinText[where + 0] = color / 2;
1291 skeleton.skinText[where + 1] = 0;
1292 skeleton.skinText[where + 2] = 0;
1297 if (creature == wolftype) {
1298 for (i = startx; i < endx; i++) {
1299 for (j = starty; j < endy; j++) {
1300 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) {
1301 color = Random() % 85 + 170;
1302 where = i * skeleton.skinsize * 3 + j * 3;
1303 if (skeleton.skinText[where + 0] > color / 2) {
1304 skeleton.skinText[where + 0] = color / 2;
1306 skeleton.skinText[where + 1] = 0;
1307 skeleton.skinText[where + 2] = 0;
1308 } 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) {
1309 color = Random() % 85 + 170;
1310 where = i * skeleton.skinsize * 3 + j * 3;
1311 if (skeleton.skinText[where + 0] > color / 2) {
1312 skeleton.skinText[where + 0] = color / 2;
1314 skeleton.skinText[where + 1] = 0;
1315 skeleton.skinText[where + 2] = 0;
1320 skeleton.drawmodel.textureptr.bind();
1323 bleedy = (1 + coordsy) * 512;
1324 bleedx = coordsx * 512;
1325 bleedy /= realtexdetail;
1326 bleedx /= realtexdetail;
1333 if (bleedx > skeleton.skinsize - 1) {
1334 bleedx = skeleton.skinsize - 1;
1336 if (bleedy > skeleton.skinsize - 1) {
1337 bleedy = skeleton.skinsize - 1;
1339 direction = abs(Random() % 2) * 2 - 1;
1341 if (whichtri == -1) {
1345 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1346 deathbleeding += bleeding;
1347 bloodloss += bleeding * 3;
1349 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1350 if (abs(Random() % 2) == 0) {
1351 aitype = gethelptype;
1354 aitype = attacktypecutoff;
1365 * guessing this performs a reversal
1367 void Person::Reverse()
1369 if (!((victim->aitype == playercontrolled || hostiletime > 1 || staggerdelay <= 0) && victim->animTarget != jumpupanim && victim->animTarget != jumpdownanim && (!Tutorial::active || cananger) && hostile)) {
1373 if (normaldotproduct(victim->facing, victim->coords - coords) > 0 && (victim->id != 0 || difficulty >= 2) && (creature != wolftype || victim->creature == wolftype)) {
1377 if (animTarget == sweepanim) {
1378 animTarget = sweepreversedanim;
1379 animCurrent = sweepreversedanim;
1380 victim->animCurrent = sweepreversalanim;
1381 victim->animTarget = sweepreversalanim;
1383 if (animTarget == spinkickanim) {
1384 animTarget = spinkickreversedanim;
1385 animCurrent = spinkickreversedanim;
1386 victim->animCurrent = spinkickreversalanim;
1387 victim->animTarget = spinkickreversalanim;
1389 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1390 if (animTarget == rabbittacklinganim) {
1393 victim->frameCurrent = 6;
1394 victim->frameTarget = 7;
1396 animTarget = upunchreversedanim;
1397 animCurrent = upunchreversedanim;
1398 victim->animCurrent = upunchreversalanim;
1399 victim->animTarget = upunchreversalanim;
1401 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1402 if (victim->weaponactive != -1) {
1403 victim->throwtogglekeydown = 1;
1404 XYZ tempVelocity = victim->velocity * .2;
1405 if (tempVelocity.x == 0) {
1406 tempVelocity.x = .1;
1408 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1409 victim->num_weapons--;
1410 if (victim->num_weapons) {
1411 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1412 if (victim->weaponstuck == victim->num_weapons) {
1413 victim->weaponstuck = 0;
1417 victim->weaponactive = -1;
1418 for (unsigned j = 0; j < Person::players.size(); j++) {
1419 Person::players[j]->wentforweapon = 0;
1423 animTarget = staffhitreversedanim;
1424 animCurrent = staffhitreversedanim;
1425 victim->animCurrent = staffhitreversalanim;
1426 victim->animTarget = staffhitreversalanim;
1428 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1429 if (victim->weaponactive != -1) {
1430 victim->throwtogglekeydown = 1;
1431 XYZ tempVelocity = victim->velocity * .2;
1432 if (tempVelocity.x == 0) {
1433 tempVelocity.x = .1;
1435 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1436 victim->num_weapons--;
1437 if (victim->num_weapons) {
1438 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1439 if (victim->weaponstuck == victim->num_weapons) {
1440 victim->weaponstuck = 0;
1444 victim->weaponactive = -1;
1445 for (unsigned j = 0; j < Person::players.size(); j++) {
1446 Person::players[j]->wentforweapon = 0;
1449 animTarget = staffspinhitreversedanim;
1450 animCurrent = staffspinhitreversedanim;
1451 victim->animCurrent = staffspinhitreversalanim;
1452 victim->animTarget = staffspinhitreversalanim;
1454 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1455 if (victim->weaponactive != -1) {
1456 victim->throwtogglekeydown = 1;
1457 XYZ tempVelocity = victim->velocity * .2;
1458 if (tempVelocity.x == 0) {
1459 tempVelocity.x = .1;
1461 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1462 victim->num_weapons--;
1463 if (victim->num_weapons) {
1464 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1465 if (victim->weaponstuck == victim->num_weapons) {
1466 victim->weaponstuck = 0;
1470 victim->weaponactive = -1;
1471 for (unsigned j = 0; j < Person::players.size(); j++) {
1472 Person::players[j]->wentforweapon = 0;
1475 animTarget = swordslashreversedanim;
1476 animCurrent = swordslashreversedanim;
1477 victim->animCurrent = swordslashreversalanim;
1478 victim->animTarget = swordslashreversalanim;
1480 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1481 if (victim->weaponactive != -1) {
1482 victim->throwtogglekeydown = 1;
1483 XYZ tempVelocity = victim->velocity * .2;
1484 if (tempVelocity.x == 0) {
1485 tempVelocity.x = .1;
1487 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1488 victim->num_weapons--;
1489 if (victim->num_weapons) {
1490 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1491 if (victim->weaponstuck == victim->num_weapons) {
1492 victim->weaponstuck = 0;
1496 victim->weaponactive = -1;
1497 for (unsigned j = 0; j < Person::players.size(); j++) {
1498 Person::players[j]->wentforweapon = 0;
1501 animTarget = knifeslashreversedanim;
1502 animCurrent = knifeslashreversedanim;
1503 victim->animCurrent = knifeslashreversalanim;
1504 victim->animTarget = knifeslashreversalanim;
1506 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1507 victim->targettilt2 = targettilt2;
1508 victim->frameCurrent = frameCurrent;
1509 victim->frameTarget = frameTarget;
1510 victim->target = target;
1511 victim->velocity = 0;
1512 victim->oldcoords = victim->coords;
1513 victim->coords = coords;
1514 victim->targetyaw = targetyaw;
1515 victim->yaw = targetyaw;
1516 victim->victim = this->shared_from_this();
1518 if (animTarget == winduppunchanim) {
1519 animTarget = winduppunchblockedanim;
1520 victim->animTarget = blockhighleftanim;
1521 victim->frameTarget = 1;
1522 victim->target = .5;
1523 victim->victim = this->shared_from_this();
1524 victim->targetyaw = targetyaw + 180;
1526 if (animTarget == wolfslapanim) {
1527 animTarget = winduppunchblockedanim;
1528 victim->animTarget = blockhighleftanim;
1529 victim->frameTarget = 1;
1530 victim->target = .5;
1531 victim->victim = this->shared_from_this();
1532 victim->targetyaw = targetyaw + 180;
1534 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1535 animTarget = swordslashparriedanim;
1536 parriedrecently = .4;
1537 victim->parriedrecently = 0;
1538 victim->animTarget = swordslashparryanim;
1539 victim->frameTarget = 1;
1540 victim->target = .5;
1541 victim->victim = this->shared_from_this();
1542 victim->targetyaw = targetyaw + 180;
1544 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1545 if (victim->weaponactive != -1) {
1546 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1547 if (weapons[victim->weaponids[0]].getType() == staff) {
1548 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1550 if (weapons[weaponids[0]].getType() == staff) {
1551 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1553 emit_sound_at(swordstaffsound, victim->coords);
1555 emit_sound_at(metalhitsound, victim->coords);
1559 victim->Puff(righthand);
1561 victim->frameTarget = 0;
1562 victim->animTarget = staggerbackhighanim;
1563 victim->targetyaw = targetyaw + 180;
1565 aim = DoRotation(facing, 0, 90, 0) * 21;
1567 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1568 victim->num_weapons--;
1569 if (victim->num_weapons) {
1570 victim->weaponids[0] = victim->weaponids[num_weapons];
1571 if (victim->weaponstuck == victim->num_weapons) {
1572 victim->weaponstuck = 0;
1575 victim->weaponactive = -1;
1576 for (unsigned i = 0; i < Person::players.size(); i++) {
1577 Person::players[i]->wentforweapon = 0;
1581 if (abs(Random() % 20) == 0) {
1582 if (weaponactive != -1) {
1583 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1584 if (weapons[victim->weaponids[0]].getType() == staff) {
1585 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1587 if (weapons[weaponids[0]].getType() == staff) {
1588 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1591 emit_sound_at(swordstaffsound, coords);
1593 emit_sound_at(metalhitsound, coords);
1601 animTarget = staggerbackhighanim;
1602 targetyaw = targetyaw + 180;
1604 aim = DoRotation(facing, 0, 90, 0) * 21;
1606 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1609 weaponids[0] = weaponids[num_weapons];
1610 if (weaponstuck == num_weapons) {
1615 for (unsigned i = 0; i < Person::players.size(); i++) {
1616 Person::players[i]->wentforweapon = 0;
1621 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1622 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1623 victim->animTarget = dodgebackanim;
1624 victim->frameTarget = 0;
1628 rotatetarget = coords - victim->coords;
1629 Normalise(&rotatetarget);
1630 victim->targetyaw = -asin(0 - rotatetarget.x);
1631 victim->targetyaw *= 360 / 6.28;
1632 if (rotatetarget.z < 0) {
1633 victim->targetyaw = 180 - victim->targetyaw;
1636 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1638 victim->lastattack3 = victim->lastattack2;
1639 victim->lastattack2 = victim->lastattack;
1640 victim->lastattack = victim->animTarget;
1642 victim->animTarget = sweepanim;
1643 victim->frameTarget = 0;
1647 rotatetarget = coords - victim->coords;
1648 Normalise(&rotatetarget);
1649 victim->targetyaw = -asin(0 - rotatetarget.x);
1650 victim->targetyaw *= 360 / 6.28;
1651 if (rotatetarget.z < 0) {
1652 victim->targetyaw = 180 - victim->targetyaw;
1655 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1657 victim->lastattack3 = victim->lastattack2;
1658 victim->lastattack2 = victim->lastattack;
1659 victim->lastattack = victim->animTarget;
1665 victim->velocity = 0;
1667 if (aitype != playercontrolled) {
1669 if (escapednum < 2) {
1670 int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
1671 if ((Random() % chances) == 0) {
1677 if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal) {
1685 void Person::DoDamage(float howmuch)
1689 damagetaken += howmuch / power;
1691 damagedealt += howmuch / power;
1695 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo)) {
1700 if (!Tutorial::active) {
1701 damage += howmuch / power;
1702 permanentdamage += howmuch / 2 / power;
1703 superpermanentdamage += howmuch / 4 / power;
1706 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2) {
1709 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt) {
1714 camerashake += howmuch / 100;
1715 if ((howmuch > 50 && damage > damagetolerance / 2)) {
1716 blackout = damage / damagetolerance;
1724 if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile)) {
1725 aitype = attacktypecutoff;
1727 if (!Tutorial::active && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1728 if (abs(Random() % 2) == 0) {
1729 aitype = gethelptype;
1732 aitype = attacktypecutoff;
1737 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1740 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1741 if (skeleton.free) {
1742 flatvelocity2 = skeleton.joints[i].velocity;
1743 flatfacing2 = skeleton.joints[i].position * scale + coords;
1745 flatvelocity2 = velocity;
1746 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1748 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1749 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1750 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1751 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1752 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1753 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1756 emit_sound_at(splattersound, coords);
1761 if (!dead && creature == wolftype) {
1762 award_bonus(0, Wolfbonus);
1769 if (!Tutorial::active || id == 0) {
1770 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1771 int whichsound = -1;
1773 if (creature == wolftype) {
1774 int i = abs(Random() % 2);
1776 whichsound = snarlsound;
1779 whichsound = snarl2sound;
1782 if (creature == rabbittype) {
1783 int i = abs(Random() % 2);
1785 whichsound = rabbitpainsound;
1787 if (i == 1 && damage > damagetolerance) {
1788 whichsound = rabbitpain1sound;
1792 if (whichsound != -1) {
1793 emit_sound_at(whichsound, coords);
1794 addEnvSound(coords);
1802 * calculate/animate head facing direction?
1804 void Person::DoHead()
1806 static XYZ rotatearound;
1808 static float lookspeed = 500;
1810 if (!freeze && !winfreeze) {
1813 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1814 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1816 while (targetheadyaw > 180) {
1817 targetheadyaw -= 360;
1819 while (targetheadyaw < -180) {
1820 targetheadyaw += 360;
1823 if (targetheadyaw > 160) {
1824 targetheadpitch = targetheadpitch * -1;
1826 if (targetheadyaw < -160) {
1827 targetheadpitch = targetheadpitch * -1;
1829 if (targetheadyaw > 160) {
1830 targetheadyaw = targetheadyaw - 180;
1832 if (targetheadyaw < -160) {
1833 targetheadyaw = targetheadyaw + 180;
1836 if (targetheadpitch > 120) {
1837 targetheadpitch = 120;
1839 if (targetheadpitch < -120) {
1840 targetheadpitch = -120;
1842 if (targetheadyaw > 120) {
1843 targetheadyaw = 120;
1845 if (targetheadyaw < -120) {
1846 targetheadyaw = -120;
1850 targetheadpitch = 0;
1853 if (targetheadyaw > 80) {
1856 if (targetheadyaw < -80) {
1857 targetheadyaw = -80;
1859 if (targetheadpitch > 50) {
1860 targetheadpitch = 50;
1862 if (targetheadpitch < -50) {
1863 targetheadpitch = -50;
1867 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed) {
1868 headyaw = targetheadyaw;
1869 } else if (headyaw > targetheadyaw) {
1870 headyaw -= multiplier * lookspeed;
1871 } else if (headyaw < targetheadyaw) {
1872 headyaw += multiplier * lookspeed;
1875 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2) {
1876 headpitch = targetheadpitch;
1877 } else if (headpitch > targetheadpitch) {
1878 headpitch -= multiplier * lookspeed / 2;
1879 } else if (headpitch < targetheadpitch) {
1880 headpitch += multiplier * lookspeed / 2;
1883 rotatearound = jointPos(neck);
1884 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1888 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1889 facing = DoRotation(facing, headpitch * .4, 0, 0);
1890 facing = DoRotation(facing, 0, headyaw * .4, 0);
1893 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1894 facing = DoRotation(facing, headpitch * .8, 0, 0);
1895 facing = DoRotation(facing, 0, headyaw * .8, 0);
1898 if (animTarget == walkanim) {
1899 facing = DoRotation(facing, headpitch * .6, 0, 0);
1900 facing = DoRotation(facing, 0, headyaw * .6, 0);
1903 skeleton.specialforward[0] = facing;
1904 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1905 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
1906 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1907 skeleton.FindRotationMuscle(i, animTarget);
1914 * ragdolls character?
1916 void Person::RagDoll(bool checkcollision)
1921 if (!skeleton.free) {
1925 if (id == 0 && isFlip()) {
1933 facing = DoRotation(facing, 0, yaw, 0);
1935 skeleton.freetime = 0;
1937 skeleton.longdead = 0;
1940 skeleton.broken = 0;
1941 skeleton.spinny = 1;
1943 skeleton.freefall = 1;
1945 if (!isnormal(velocity.x)) {
1948 if (!isnormal(velocity.y)) {
1951 if (!isnormal(velocity.z)) {
1954 if (!isnormal(yaw)) {
1957 if (!isnormal(coords.x)) {
1960 if (!isnormal(tilt)) {
1963 if (!isnormal(tilt2)) {
1967 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1968 skeleton.joints[i].delay = 0;
1969 skeleton.joints[i].locked = 0;
1970 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1971 if (!isnormal(skeleton.joints[i].position.x)) {
1972 skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1974 if (!isnormal(skeleton.joints[i].position.x)) {
1975 skeleton.joints[i].position = coords;
1977 skeleton.joints[i].position.y += .1;
1978 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1979 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1982 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1983 skeleton.joints[i].velocity = 0;
1984 skeleton.joints[i].velchange = 0;
1986 skeleton.DoConstraints(&coords, &scale);
1987 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
1988 skeleton.DoConstraints(&coords, &scale);
1989 skeleton.DoConstraints(&coords, &scale);
1990 skeleton.DoConstraints(&coords, &scale);
1991 skeleton.DoConstraints(&coords, &scale);
1994 speed = targetFrame().speed * 2;
1995 if (currentFrame().speed > targetFrame().speed) {
1996 speed = currentFrame().speed * 2;
1999 speed = transspeed * 2;
2004 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
2005 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height) {
2006 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);
2008 skeleton.joints[i].velocity = velocity / scale + facing * 5;
2010 change.x = (float)(Random() % 100) / 100;
2011 change.y = (float)(Random() % 100) / 100;
2012 change.z = (float)(Random() % 100) / 100;
2013 skeleton.joints[i].velocity += change;
2014 skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change;
2016 change.x = (float)(Random() % 100) / 100;
2017 change.y = (float)(Random() % 100) / 100;
2018 change.z = (float)(Random() % 100) / 100;
2019 skeleton.joints[i].velchange += change;
2020 skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change;
2023 if (checkcollision) {
2026 if (!skeleton.joints.empty()) {
2029 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
2030 average += skeleton.joints[j].position;
2032 average /= skeleton.joints.size();
2033 coords += average * scale;
2034 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
2035 skeleton.joints[j].position -= average;
2039 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
2040 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
2041 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
2042 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
2045 if (SphereCheck(&lowpoint, 3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
2046 coords.x = lowpoint.x;
2047 coords.z = lowpoint.z;
2056 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
2057 velocity += skeleton.joints[i].velocity * scale;
2059 velocity /= skeleton.joints.size();
2062 if (Random() % 2 == 0) {
2063 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
2064 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
2065 weapons[weaponids[0]].velocity.x += .01;
2068 weaponids[0] = weaponids[num_weapons];
2069 if (weaponstuck == num_weapons) {
2074 for (unsigned i = 0; i < Person::players.size(); i++) {
2075 Person::players[i]->wentforweapon = 0;
2080 animTarget = bounceidleanim;
2081 animCurrent = bounceidleanim;
2089 void Person::FootLand(bodypart whichfoot, float opacity)
2091 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
2092 cerr << "FootLand called on wrong bodypart" << endl;
2095 static XYZ terrainlight;
2096 static XYZ footvel, footpoint;
2097 if (opacity >= 1 || skiddelay <= 0) {
2100 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2101 if (distsq(&footpoint, &viewer)) {
2102 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
2104 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
2105 footvel = velocity / 5;
2106 if (footvel.y < .8) {
2109 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2110 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
2111 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
2112 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
2113 if (environment == snowyenvironment) {
2114 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
2116 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
2118 } else if (environment == grassyenvironment) {
2119 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
2120 } else if (environment == desertenvironment) {
2121 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
2123 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
2127 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
2128 footvel = velocity / 5;
2129 if (footvel.y < .8) {
2132 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2133 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
2134 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
2141 * make a puff effect at a body part (dust effect?)
2143 void Person::Puff(int whichlabel)
2145 static XYZ footvel, footpoint;
2148 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
2149 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
2153 * I think I added this in an attempt to clean up code
2155 void Person::setTargetAnimation(int animation)
2157 animTarget = animation;
2166 void Person::DoAnimations()
2168 if (!skeleton.free) {
2169 static float oldtarget;
2171 if (isIdle() && animCurrent != getIdle()) {
2172 normalsupdatedelay = 0;
2175 if (animTarget == tempanim || animCurrent == tempanim) {
2176 Animation::animations[tempanim] = tempanimation;
2178 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
2185 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
2186 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
2188 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z)) {
2191 if (!crouchkeydown && velocity.y >= -15) {
2195 if ((animCurrent == jumpupanim || animTarget == jumpdownanim) /*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
2200 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
2202 if (normaldotproduct(targfacing, velocity) >= -.3) {
2203 animTarget = flipanim;
2205 animTarget = backflipanim;
2207 crouchtogglekeydown = 1;
2216 if (Animation::animations[animTarget].attack != reversed) {
2219 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
2220 crouchtogglekeydown = 0;
2221 if (aitype == playercontrolled) {
2225 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain)) {
2229 crouchtogglekeydown = 1;
2233 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
2235 normalsupdatedelay = 0;
2240 if (animTarget == rollanim && frameTarget == 3 && onfire) {
2242 emit_sound_at(fireendsound, coords);
2243 pause_sound(stream_firesound);
2247 if (animTarget == rabbittacklinganim && frameTarget == 1) {
2248 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0) {
2251 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
2252 if (normaldotproduct(victim->facing, facing) > 0) {
2253 victim->animTarget = rabbittackledbackanim;
2255 victim->animTarget = rabbittackledfrontanim;
2257 victim->frameTarget = 2;
2260 victim->targetyaw = yaw;
2261 if (victim->aitype == gethelptype) {
2262 victim->DoDamage(victim->damagetolerance - victim->damage);
2264 //victim->DoDamage(30);
2265 if (creature == wolftype) {
2267 emit_sound_at(clawslicesound, victim->coords);
2269 victim->DoBloodBig(1 / victim->armorhead, 210);
2271 award_bonus(id, TackleBonus,
2272 victim->aitype == gethelptype ? 50 : 0);
2276 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2277 if (weapons[weaponids[0]].getType() == knife) {
2278 if (weaponactive == -1) {
2280 } else if (weaponactive == 0) {
2284 if (weaponactive == -1) {
2285 emit_sound_at(knifesheathesound, coords);
2287 if (weaponactive != -1) {
2288 emit_sound_at(knifedrawsound, coords, 128);
2291 drawtogglekeydown = 1;
2294 if (!Tutorial::active || id == 0) {
2295 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2296 int whichsound = -1;
2298 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2299 if (targetFrame().label == 1) {
2300 whichsound = footstepsound;
2302 whichsound = footstepsound2;
2304 if (targetFrame().label == 1) {
2305 FootLand(leftfoot, 1);
2307 if (targetFrame().label == 2) {
2308 FootLand(rightfoot, 1);
2310 if (targetFrame().label == 3 && isRun()) {
2311 FootLand(rightfoot, 1);
2312 FootLand(leftfoot, 1);
2315 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2316 if (targetFrame().label == 1) {
2317 whichsound = footstepsound3;
2319 whichsound = footstepsound4;
2324 if (targetFrame().label == 1) {
2325 whichsound = footstepsound3;
2327 whichsound = footstepsound4;
2330 if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2331 if (Animation::animations[animTarget].attack != neutral) {
2332 unsigned r = abs(Random() % 3);
2334 whichsound = lowwhooshsound;
2337 whichsound = midwhooshsound;
2340 whichsound = highwhooshsound;
2343 if (Animation::animations[animTarget].attack == neutral) {
2344 whichsound = movewhooshsound;
2346 } else if (targetFrame().label == 4) {
2347 whichsound = knifeswishsound;
2349 if (targetFrame().label == 8 && !Tutorial::active) {
2350 whichsound = landsound2;
2353 if (whichsound != -1) {
2354 emit_sound_at(whichsound, coords, 256.);
2357 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2358 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2359 addEnvSound(coords, 15);
2361 addEnvSound(coords, 6);
2366 if (targetFrame().label == 3) {
2368 emit_sound_at(whichsound, coords, 128.);
2375 if (!Tutorial::active || id == 0) {
2376 if (speechdelay <= 0) {
2377 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
2378 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2379 int whichsound = -1;
2380 if (targetFrame().label == 4 && aitype != playercontrolled) {
2381 if (Animation::animations[animTarget].attack != neutral) {
2382 unsigned r = abs(Random() % 4);
2383 if (creature == rabbittype) {
2385 whichsound = rabbitattacksound;
2388 whichsound = rabbitattack2sound;
2391 whichsound = rabbitattack3sound;
2394 whichsound = rabbitattack4sound;
2397 if (creature == wolftype) {
2399 whichsound = barksound;
2402 whichsound = bark2sound;
2405 whichsound = bark3sound;
2408 whichsound = barkgrowlsound;
2415 if (whichsound != -1) {
2416 emit_sound_at(whichsound, coords);
2423 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2424 FootLand(leftfoot, 1);
2425 FootLand(rightfoot, 1);
2429 currentoffset = targetoffset;
2430 frameTarget = frameCurrent;
2431 animCurrent = animTarget;
2434 if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2435 for (unsigned i = 0; i < weapons.size(); i++) {
2436 if (weapons[i].owner == -1) {
2437 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2438 if (distsq(&coords, &weapons[i].position) >= 1) {
2439 if (weapons[i].getType() != staff) {
2440 emit_sound_at(knifedrawsound, coords, 128.);
2450 if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2451 for (unsigned i = 0; i < weapons.size(); i++) {
2452 bool willwork = true;
2453 if (weapons[i].owner != -1) {
2454 if (Person::players[weapons[i].owner]->weaponstuck != -1) {
2455 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i)) {
2456 if (Person::players[weapons[i].owner]->num_weapons > 1) {
2462 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free)) {
2463 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2464 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2465 bool fleshstuck = false;
2466 if (weapons[i].owner != -1) {
2467 if (victim->weaponstuck != -1) {
2468 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2474 emit_sound_at(fleshstabremovesound, coords, 128.);
2476 if (weapons[i].getType() != staff) {
2477 emit_sound_at(knifedrawsound, coords, 128.);
2480 if (weapons[i].owner != -1) {
2481 victim = Person::players[weapons[i].owner];
2482 if (victim->num_weapons == 1) {
2483 victim->num_weapons = 0;
2485 victim->num_weapons = 1;
2488 //victim->weaponactive=-1;
2489 victim->skeleton.longdead = 0;
2490 victim->skeleton.free = 1;
2491 victim->skeleton.broken = 0;
2493 for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) {
2494 victim->skeleton.joints[j].velchange = 0;
2495 victim->skeleton.joints[j].locked = 0;
2501 Normalise(&relative);
2502 XYZ footvel, footpoint;
2504 footpoint = weapons[i].position;
2505 if (victim->weaponstuck != -1) {
2506 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2508 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2510 weapons[i].bloody = 2;
2511 weapons[i].blooddrip = 5;
2512 victim->weaponstuck = -1;
2515 if (victim->num_weapons > 0) {
2516 if (victim->weaponstuck != 0 && victim->weaponstuck != -1) {
2517 victim->weaponstuck = 0;
2519 if (victim->weaponids[0] == int(i)) {
2520 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2524 victim->jointVel(abdomen) += relative * 6;
2525 victim->jointVel(neck) += relative * 6;
2526 victim->jointVel(rightshoulder) += relative * 6;
2527 victim->jointVel(leftshoulder) += relative * 6;
2536 if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2537 if (weaponactive == -1) {
2539 } else if (weaponactive == 0) {
2541 if (num_weapons == 2) {
2543 buffer = weaponids[0];
2544 weaponids[0] = weaponids[1];
2545 weaponids[1] = buffer;
2548 if (weaponactive == -1) {
2549 emit_sound_at(knifesheathesound, coords, 128.);
2551 if (weaponactive != -1) {
2552 emit_sound_at(knifedrawsound, coords, 128.);
2556 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2557 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2558 Normalise(&rotatetarget);
2559 targetyaw = -asin(0 - rotatetarget.x);
2560 targetyaw *= 360 / 6.28;
2561 if (rotatetarget.z < 0) {
2562 targetyaw = 180 - targetyaw;
2565 if (animTarget == walljumprightkickanim) {
2568 if (animTarget == walljumpleftkickanim) {
2575 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0)) {
2579 if (distsq(&victim->coords, &/*Person::players[i]->*/ coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1) {
2587 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2588 animTarget = rabbittackleanim;
2590 emit_sound_at(jumpsound, coords);
2598 targetloc = velocity;
2599 Normalise(&targetloc);
2600 targetloc += coords;
2601 for (unsigned i = 0; i < Person::players.size(); i++) {
2603 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2604 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2609 if (closestid != -1) {
2610 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2612 victim = Person::players[closestid];
2613 coords = victim->coords;
2614 animCurrent = rabbittacklinganim;
2615 animTarget = rabbittacklinganim;
2619 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2620 rotatetarget = coords - victim->coords;
2621 Normalise(&rotatetarget);
2622 targetyaw = -asin(0 - rotatetarget.x);
2623 targetyaw *= 360 / 6.28;
2624 if (rotatetarget.z < 0) {
2625 targetyaw = 180 - targetyaw;
2628 if (animTarget != rabbitrunninganim) {
2629 emit_sound_at(jumpsound, coords, 128.);
2636 float damagemult = 1 * power;
2637 if (creature == wolftype) {
2638 damagemult = 2.5 * power;
2641 damagemult /= victim->damagetolerance / 200;
2643 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)) {
2644 if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2645 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2650 if (Random() % 2 || creature == wolftype) {
2653 if (creature == wolftype) {
2657 if (!Tutorial::active) {
2658 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2660 if (creature == wolftype) {
2661 emit_sound_at(clawslicesound, victim->coords, 128.);
2663 victim->DoBloodBig(2 / victim->armorhead, 175);
2667 relative = victim->coords - coords;
2669 Normalise(&relative);
2670 relative = DoRotation(relative, 0, -90, 0);
2671 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2672 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2674 victim->jointVel(head) += relative * damagemult * 200;
2676 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2682 if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2683 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2688 if (Random() % 2 || creature == wolftype) {
2690 if (creature == wolftype) {
2694 emit_sound_at(whooshhitsound, victim->coords);
2695 if (creature == wolftype) {
2696 emit_sound_at(clawslicesound, victim->coords, 128.);
2698 victim->DoBloodBig(2, 175);
2702 relative = victim->coords - coords;
2704 Normalise(&relative);
2706 Normalise(&relative);
2707 relative = DoRotation(relative, 0, 90, 0);
2708 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2709 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2711 victim->jointVel(head) += relative * damagemult * 100;
2713 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2717 if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2718 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2725 if (!Tutorial::active) {
2726 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2728 if (creature == wolftype) {
2729 emit_sound_at(clawslicesound, victim->coords, 128.);
2731 victim->DoBloodBig(2 / victim->armorhead, 175);
2737 Normalise(&relative);
2738 relative = DoRotation(relative, 0, -90, 0);
2739 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2740 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2742 victim->jointVel(head) += relative * damagemult * 200;
2744 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2746 if (victim->damage > victim->damagetolerance) {
2747 award_bonus(id, style);
2754 if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2755 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2762 if (!Tutorial::active) {
2763 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2765 if (creature == wolftype) {
2766 emit_sound_at(clawslicesound, victim->coords, 128.);
2768 victim->DoBloodBig(2 / victim->armorhead, 175);
2774 Normalise(&relative);
2775 relative = DoRotation(relative, 0, 90, 0);
2776 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2777 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2779 victim->jointVel(head) += relative * damagemult * 200;
2781 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2783 if (victim->damage > victim->damagetolerance) {
2784 award_bonus(id, style);
2791 if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2792 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2801 emit_sound_at(whooshhitsound, victim->coords);
2804 relative = victim->coords - coords;
2806 Normalise(&relative);
2807 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2808 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2810 victim->jointVel(head) += relative * damagemult * 100;
2812 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2816 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
2817 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2822 emit_sound_at(whooshhitsound, victim->coords, 128.);
2824 victim->skeleton.longdead = 0;
2825 victim->skeleton.free = 1;
2826 victim->skeleton.broken = 0;
2827 victim->skeleton.spinny = 1;
2829 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2830 victim->skeleton.joints[i].velchange = 0;
2831 victim->skeleton.joints[i].delay = 0;
2832 victim->skeleton.joints[i].locked = 0;
2833 //victim->skeleton.joints[i].velocity=0;
2839 Normalise(&relative);
2840 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2841 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2842 victim->skeleton.joints[i].position.y += relative.y * .3;
2843 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2844 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2846 victim->Puff(abdomen);
2847 victim->jointVel(abdomen).y = relative.y * 400;
2851 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2852 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2857 if (!Tutorial::active) {
2858 emit_sound_at(heavyimpactsound, coords, 128.);
2861 relative = victim->coords - coords;
2863 Normalise(&relative);
2864 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2865 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2867 victim->Puff(abdomen);
2868 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2872 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2873 victim->jointVel(abdomen) += relative * damagemult * 300;
2877 if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
2878 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2883 if (!Tutorial::active) {
2884 emit_sound_at(thudsound, coords);
2887 victim->skeleton.longdead = 0;
2888 victim->skeleton.free = 1;
2889 victim->skeleton.broken = 0;
2890 victim->skeleton.spinny = 1;
2892 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2893 victim->skeleton.joints[i].velchange = 0;
2894 //victim->skeleton.joints[i].delay=0;
2895 victim->skeleton.joints[i].locked = 0;
2898 relative = victim->coords - coords;
2899 Normalise(&relative);
2901 Normalise(&relative);
2902 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2903 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2905 if (!victim->dead) {
2909 victim->Puff(abdomen);
2910 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2911 victim->jointVel(abdomen) += relative * damagemult * 200;
2913 if (!victim->dead) {
2919 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2922 if (!victim->skeleton.free) {
2928 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2929 emit_sound_at(knifesheathesound, coords, 128.);
2932 if (victim && hasvictim) {
2933 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2935 XYZ where, startpoint, endpoint, movepoint, colpoint;
2936 float rotationpoint;
2938 if (weapons[weaponids[weaponactive]].getType() == knife) {
2939 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2940 where -= victim->coords;
2941 if (!victim->skeleton.free) {
2942 where = DoRotation(where, 0, -victim->yaw, 0);
2946 startpoint.y += 100;
2950 if (weapons[weaponids[weaponactive]].getType() == sword) {
2951 where = weapons[weaponids[weaponactive]].position;
2952 where -= victim->coords;
2953 if (!victim->skeleton.free) {
2954 where = DoRotation(where, 0, -victim->yaw, 0);
2957 where = weapons[weaponids[weaponactive]].tippoint;
2958 where -= victim->coords;
2959 if (!victim->skeleton.free) {
2960 where = DoRotation(where, 0, -victim->yaw, 0);
2964 if (weapons[weaponids[weaponactive]].getType() == staff) {
2965 where = weapons[weaponids[weaponactive]].position;
2966 where -= victim->coords;
2967 if (!victim->skeleton.free) {
2968 where = DoRotation(where, 0, -victim->yaw, 0);
2971 where = weapons[weaponids[weaponactive]].tippoint;
2972 where -= victim->coords;
2973 if (!victim->skeleton.free) {
2974 where = DoRotation(where, 0, -victim->yaw, 0);
2980 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2982 if (whichtri != -1) {
2983 if (victim->dead != 2) {
2984 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2985 if (!victim->dead) {
2986 award_bonus(id, FinishedBonus);
2990 weapons[weaponids[weaponactive]].bloody = 2;
2993 victim->skeleton.longdead = 0;
2994 victim->skeleton.free = 1;
2995 victim->skeleton.broken = 0;
2997 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2998 victim->skeleton.joints[i].velchange = 0;
2999 victim->skeleton.joints[i].locked = 0;
3000 //victim->skeleton.joints[i].velocity=0;
3002 emit_sound_at(fleshstabsound, coords, 128);
3004 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
3005 weapons[weaponids[weaponactive]].blooddrip += 5;
3006 weapons[weaponids[weaponactive]].blooddripdelay = 0;
3008 if (whichtri == -1) {
3010 emit_sound_at(knifesheathesound, coords, 128.);
3016 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3018 emit_sound_at(knifedrawsound, coords, 128);
3021 if (victim && hasvictim) {
3022 XYZ footvel, footpoint;
3024 emit_sound_at(fleshstabremovesound, coords, 128.);
3027 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
3029 if (weapons[weaponids[weaponactive]].getType() == sword) {
3030 XYZ where, startpoint, endpoint, movepoint;
3031 float rotationpoint;
3034 where = weapons[weaponids[weaponactive]].position;
3035 where -= victim->coords;
3036 if (!victim->skeleton.free) {
3037 where = DoRotation(where, 0, -victim->yaw, 0);
3040 where = weapons[weaponids[weaponactive]].tippoint;
3041 where -= victim->coords;
3042 if (!victim->skeleton.free) {
3043 where = DoRotation(where, 0, -victim->yaw, 0);
3049 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
3050 footpoint += victim->coords;
3052 if (whichtri == -1) {
3053 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
3056 if (weapons[weaponids[weaponactive]].getType() == staff) {
3057 XYZ where, startpoint, endpoint, movepoint;
3058 float rotationpoint;
3061 where = weapons[weaponids[weaponactive]].position;
3062 where -= victim->coords;
3063 if (!victim->skeleton.free) {
3064 where = DoRotation(where, 0, -victim->yaw, 0);
3067 where = weapons[weaponids[weaponactive]].tippoint;
3068 where -= victim->coords;
3069 if (!victim->skeleton.free) {
3070 where = DoRotation(where, 0, -victim->yaw, 0);
3076 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
3077 footpoint += victim->coords;
3079 if (whichtri == -1) {
3080 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
3083 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
3085 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
3086 victim->skeleton.longdead = 0;
3087 victim->skeleton.free = 1;
3088 victim->skeleton.broken = 0;
3090 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3091 victim->skeleton.joints[i].velchange = 0;
3092 victim->skeleton.joints[i].locked = 0;
3093 //victim->skeleton.joints[i].velocity=0;
3099 Normalise(&relative);
3100 //victim->Puff(abdomen);
3102 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
3105 if (victim->bloodloss < victim->damagetolerance) {
3106 victim->bloodloss += 1000;
3110 victim->jointVel(abdomen) += relative * damagemult * 20;
3114 if (!hasvictim && onterrain) {
3115 weapons[weaponids[weaponactive]].bloody = 0;
3116 weapons[weaponids[weaponactive]].blooddrip = 0;
3120 if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3121 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
3130 if (!Tutorial::active) {
3131 emit_sound_at(heavyimpactsound, victim->coords, 128);
3136 relative = victim->coords - coords;
3138 Normalise(&relative);
3139 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3140 victim->skeleton.joints[i].velocity = relative * 30;
3142 victim->jointVel(head) += relative * damagemult * 150;
3144 victim->frameTarget = 0;
3145 victim->animTarget = staggerbackhardanim;
3146 victim->targetyaw = targetyaw + 180;
3148 victim->stunned = 1;
3151 victim->Puff(abdomen);
3152 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
3158 if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3159 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
3164 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
3165 if (!Tutorial::active) {
3166 emit_sound_at(thudsound, victim->coords);
3168 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
3169 if (!Tutorial::active) {
3170 emit_sound_at(whooshhitsound, victim->coords);
3173 if (!Tutorial::active) {
3174 emit_sound_at(heavyimpactsound, victim->coords);
3178 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight) {
3182 relative = victim->coords - coords;
3184 Normalise(&relative);
3186 Normalise(&relative);
3187 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3188 victim->skeleton.joints[i].velocity = relative * 5;
3190 victim->jointVel(abdomen) += relative * damagemult * 400;
3192 victim->frameTarget = 0;
3193 victim->animTarget = staggerbackhardanim;
3194 victim->targetyaw = targetyaw + 180;
3196 victim->stunned = 1;
3198 victim->Puff(abdomen);
3199 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
3205 if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3206 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3207 if (victim->id == 0) {
3210 emit_sound_at(landsound2, victim->coords);
3216 if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3217 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3218 if (victim->id == 0) {
3222 if (weaponactive != -1) {
3223 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3224 if (weapons[victim->weaponids[0]].getType() == staff) {
3225 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3227 if (weapons[weaponids[0]].getType() == staff) {
3228 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3231 emit_sound_at(swordstaffsound, victim->coords);
3233 emit_sound_at(metalhitsound, victim->coords);
3241 if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3242 if (weaponactive != -1) {
3245 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);
3247 weapons[weaponids[0]].thrown(aim * 50);
3250 weaponids[0] = weaponids[num_weapons];
3256 if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3258 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 && /*Animation::animations[victim->animTarget].height!=lowheight&&*/ victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
3260 if (!Tutorial::active) {
3261 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
3264 award_bonus(id, Slicebonus);
3265 if (!Tutorial::active) {
3266 emit_sound_at(knifeslicesound, victim->coords);
3268 //victim->jointVel(abdomen)+=relative*damagemult*200;
3269 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
3270 if (victim->id != 0 || difficulty == 2) {
3271 victim->frameTarget = 0;
3272 victim->animTarget = staggerbackhardanim;
3273 victim->targetyaw = targetyaw + 180;
3277 victim->lowreversaldelay = 0;
3278 victim->highreversaldelay = 0;
3279 if (aitype != playercontrolled) {
3280 weaponmissdelay = .6;
3283 if (!Tutorial::active) {
3284 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3285 weapons[weaponids[weaponactive]].bloody = 1;
3287 weapons[weaponids[weaponactive]].blooddrip += 3;
3290 XYZ footvel, footpoint;
3292 if (skeleton.free) {
3293 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3295 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3297 if (Tutorial::active) {
3298 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
3301 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
3303 footvel = DoRotation(facing, 0, 90, 0) * .8;
3304 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3305 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3306 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3307 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3309 victim->DoDamage(damagemult * 0);
3313 if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3314 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
3315 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
3316 award_bonus(id, Slashbonus);
3318 if (!Tutorial::active) {
3319 if (normaldotproduct(victim->facing, victim->coords - coords) < 0) {
3320 victim->DoBloodBig(2 / victim->armorhigh, 190);
3322 victim->DoBloodBig(2 / victim->armorhigh, 185);
3324 victim->deathbleeding = 1;
3325 emit_sound_at(swordslicesound, victim->coords);
3326 victim->frameTarget = 0;
3327 victim->animTarget = staggerbackhardanim;
3328 victim->targetyaw = targetyaw + 180;
3330 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3331 weapons[weaponids[weaponactive]].bloody = 1;
3333 weapons[weaponids[weaponactive]].blooddrip += 3;
3335 float bloodlossamount;
3336 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
3337 victim->bloodloss += bloodlossamount / victim->armorhigh;
3338 victim->DoDamage(damagemult * 0);
3340 XYZ footvel, footpoint;
3342 if (skeleton.free) {
3343 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3345 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3348 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3350 footvel = DoRotation(facing, 0, 90, 0) * .8;
3352 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3353 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3354 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3355 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3358 if (victim->weaponactive != -1) {
3359 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3360 if (weapons[victim->weaponids[0]].getType() == staff) {
3361 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3363 if (weapons[weaponids[0]].getType() == staff) {
3364 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3367 emit_sound_at(swordstaffsound, victim->coords);
3369 emit_sound_at(metalhitsound, victim->coords);
3374 victim->Puff(righthand);
3376 victim->frameTarget = 0;
3377 victim->animTarget = staggerbackhighanim;
3378 victim->targetyaw = targetyaw + 180;
3380 aim = DoRotation(facing, 0, 90, 0) * 21;
3382 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3383 victim->num_weapons--;
3384 if (victim->num_weapons) {
3385 victim->weaponids[0] = victim->weaponids[num_weapons];
3386 if (victim->weaponstuck == victim->num_weapons) {
3387 victim->weaponstuck = 0;
3390 victim->weaponactive = -1;
3391 for (unsigned i = 0; i < Person::players.size(); i++) {
3392 Person::players[i]->wentforweapon = 0;
3398 if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3399 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3400 if (!Tutorial::active) {
3401 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3406 if (Random() % 2 || creature == wolftype) {
3409 emit_sound_at(staffheadsound, victim->coords);
3413 relative = victim->coords - coords;
3415 Normalise(&relative);
3416 relative = DoRotation(relative, 0, 90, 0);
3418 Normalise(&relative);
3419 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3420 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3422 victim->jointVel(head) += relative * damagemult * 230;
3423 victim->jointVel(neck) += relative * damagemult * 230;
3425 if (!Tutorial::active) {
3426 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3428 award_bonus(id, solidhit, 30);
3433 if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3434 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3435 if (!Tutorial::active) {
3436 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3441 if (Random() % 2 || creature == wolftype) {
3444 emit_sound_at(staffheadsound, victim->coords);
3448 relative = victim->coords - coords;
3450 Normalise(&relative);
3451 relative = DoRotation(relative, 0, -90, 0);
3452 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3453 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3455 victim->jointVel(head) += relative * damagemult * 220;
3456 victim->jointVel(neck) += relative * damagemult * 220;
3458 if (!Tutorial::active) {
3459 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3461 award_bonus(id, solidhit, 60);
3466 if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3467 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3469 if (!Tutorial::active) {
3470 if (!victim->dead) {
3471 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3476 if (Random() % 2 || creature == wolftype) {
3479 emit_sound_at(staffbodysound, victim->coords);
3481 victim->skeleton.longdead = 0;
3482 victim->skeleton.free = 1;
3483 victim->skeleton.broken = 0;
3485 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3486 victim->skeleton.joints[i].velchange = 0;
3487 victim->skeleton.joints[i].locked = 0;
3488 //victim->skeleton.joints[i].velocity=0;
3495 Normalise(&relative);
3496 if (!victim->dead) {
3497 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3498 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3500 victim->jointVel(abdomen) += relative * damagemult * 40;
3503 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3504 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3507 victim->Puff(abdomen);
3508 if (!Tutorial::active) {
3509 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3511 if (!victim->dead) {
3512 award_bonus(id, solidhit, 40);
3518 if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3519 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3525 relative = victim->coords - coords;
3527 Normalise(&relative);
3531 if (Animation::animations[victim->animTarget].height == lowheight) {
3537 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3538 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3540 victim->jointVel(head) += relative * damagemult * 200;
3541 if (!Tutorial::active) {
3542 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3545 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3546 if (victim->howactive == typesleeping) {
3547 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3549 if (creature == wolftype) {
3550 emit_sound_at(clawslicesound, victim->coords, 128.);
3552 victim->DoBloodBig(2 / victim->armorhead, 175);
3555 if (victim->damage >= victim->damagetolerance) {
3558 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3559 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3561 victim->jointVel(abdomen) += relative * damagemult * 200;
3562 victim->frameTarget = 0;
3563 victim->animTarget = staggerbackhighanim;
3564 victim->targetyaw = targetyaw + 180;
3566 if (!Tutorial::active) {
3567 emit_sound_at(landsound2, victim->coords, 128.);
3569 victim->Puff(abdomen);
3570 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3571 if (creature == wolftype) {
3572 emit_sound_at(clawslicesound, victim->coords, 128.);
3574 victim->DoBloodBig(2 / victim->armorhigh, 170);
3580 if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3581 if ((victim->animTarget != jumpupanim) &&
3582 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3583 (victim != this->shared_from_this())) {
3588 if (!Tutorial::active) {
3589 emit_sound_at(landsound2, victim->coords, 128.);
3592 relative = victim->coords - coords;
3594 Normalise(&relative);
3596 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3599 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3600 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3602 relative = DoRotation(relative, 0, -90, 0);
3604 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3605 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) {
3606 victim->skeleton.joints[i].velocity = relative * 80;
3609 victim->Puff(rightankle);
3610 victim->Puff(leftankle);
3611 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3613 if (victim->damage >= victim->damagetolerance) {
3616 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3617 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3619 relative = DoRotation(relative, 0, -90, 0);
3620 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3621 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) {
3622 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3625 victim->jointVel(abdomen) += relative * damagemult * 200;
3626 victim->frameTarget = 0;
3627 victim->animTarget = staggerbackhighanim;
3628 victim->targetyaw = targetyaw + 180;
3630 if (!Tutorial::active) {
3631 emit_sound_at(landsound2, victim->coords, 128.);
3633 victim->Puff(abdomen);
3634 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3641 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3642 if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3651 if (!Tutorial::active) {
3652 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3654 if (creature == wolftype) {
3655 emit_sound_at(clawslicesound, victim->coords, 128);
3657 victim->DoBloodBig(2 / victim->armorhigh, 170);
3661 relative = victim->coords - oldcoords;
3663 Normalise(&relative);
3664 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3665 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3667 victim->jointVel(abdomen) += relative * damagemult * 200;
3668 victim->Puff(abdomen);
3669 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3671 award_bonus(id, Reversal);
3674 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3675 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3676 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3677 takeWeapon(victim->weaponids[victim->weaponactive]);
3678 victim->num_weapons--;
3679 if (victim->num_weapons > 0) {
3680 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3682 victim->weaponactive = -1;
3687 if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3696 emit_sound_at(whooshhitsound, victim->coords, 128.);
3699 relative = victim->coords - oldcoords;
3701 Normalise(&relative);
3702 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3703 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3705 victim->jointVel(abdomen) += relative * damagemult * 200;
3707 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3710 if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3720 award_bonus(id, staffreversebonus);
3722 if (!Tutorial::active) {
3723 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3726 award_bonus(id, staffreversebonus); // Huh, again?
3729 relative = victim->coords - oldcoords;
3731 Normalise(&relative);
3732 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3733 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3735 victim->jointVel(abdomen) += relative * damagemult * 200;
3737 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3740 if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3746 Normalise(&relative);
3748 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3749 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3751 victim->jointVel(lefthand) *= .1;
3752 victim->jointVel(leftwrist) *= .2;
3753 victim->jointVel(leftelbow) *= .5;
3754 victim->jointVel(leftshoulder) *= .7;
3755 victim->jointVel(righthand) *= .1;
3756 victim->jointVel(rightwrist) *= .2;
3757 victim->jointVel(rightelbow) *= .5;
3758 victim->jointVel(rightshoulder) *= .7;
3760 victim->Puff(abdomen);
3761 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3763 award_bonus(id, Reversal);
3767 if (weaponactive != -1 || creature == wolftype) {
3770 if (creature == rabbittype && weaponactive != -1) {
3771 if (weapons[weaponids[0]].getType() == staff) {
3776 if (weaponactive != -1) {
3777 victim->DoBloodBig(2 / victim->armorhigh, 225);
3778 emit_sound_at(knifeslicesound, victim->coords);
3779 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3780 weapons[weaponids[weaponactive]].bloody = 1;
3782 weapons[weaponids[weaponactive]].blooddrip += 3;
3784 if (weaponactive == -1 && creature == wolftype) {
3785 emit_sound_at(clawslicesound, victim->coords, 128.);
3787 victim->DoBloodBig(2 / victim->armorhigh, 175);
3792 if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3798 Normalise(&relative);
3800 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3801 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3803 victim->jointVel(lefthand) *= .1 - 1;
3804 victim->jointVel(leftwrist) *= .2 - 1;
3805 victim->jointVel(leftelbow) *= .5 - 1;
3806 victim->jointVel(leftshoulder) *= .7 - 1;
3807 victim->jointVel(righthand) *= .1 - 1;
3808 victim->jointVel(rightwrist) *= .2 - 1;
3809 victim->jointVel(rightelbow) *= .5 - 1;
3810 victim->jointVel(rightshoulder) *= .7 - 1;
3812 award_bonus(id, swordreversebonus);
3815 if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3824 if (!Tutorial::active) {
3825 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3829 relative = victim->coords - oldcoords;
3831 Normalise(&relative);
3832 relative = DoRotation(relative, 0, -90, 0);
3833 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3834 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3836 victim->jointVel(abdomen) += relative * damagemult * 200;
3837 victim->Puff(abdomen);
3838 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3840 award_bonus(id, Reversal);
3843 if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3846 victim->skeleton.spinny = 0;
3848 relative = facing * -1;
3850 Normalise(&relative);
3851 if (victim->id == 0) {
3854 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3855 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3857 victim->damage = victim->damagetolerance;
3858 victim->permanentdamage = victim->damagetolerance - 1;
3861 if (weaponactive != -1 || creature == wolftype) {
3864 if (creature == rabbittype && weaponactive != -1) {
3865 if (weapons[weaponids[0]].getType() == staff) {
3870 if (weaponactive != -1) {
3871 victim->DoBloodBig(200, 225);
3872 emit_sound_at(knifeslicesound, victim->coords);
3874 weapons[weaponids[weaponactive]].bloody = 2;
3876 weapons[weaponids[weaponactive]].blooddrip += 5;
3879 if (creature == wolftype && weaponactive == -1) {
3880 emit_sound_at(clawslicesound, victim->coords, 128.);
3882 victim->DoBloodBig(2, 175);
3885 award_bonus(id, spinecrusher);
3888 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3889 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3891 if (animTarget == knifefollowanim) {
3892 victim->DoBloodBig(200, 210);
3894 if (animTarget == knifesneakattackanim) {
3895 XYZ footvel, footpoint;
3897 footpoint = weapons[weaponids[0]].tippoint;
3899 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3901 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3902 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3903 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3904 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3905 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3906 victim->DoBloodBig(200, 195);
3907 award_bonus(id, tracheotomy);
3909 if (animTarget == knifefollowanim) {
3910 award_bonus(id, Stabbonus);
3911 XYZ footvel, footpoint;
3913 footpoint = weapons[weaponids[0]].tippoint;
3915 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3917 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3918 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3919 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3920 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3921 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3923 victim->bloodloss += 10000;
3924 victim->velocity = 0;
3925 emit_sound_at(fleshstabsound, victim->coords);
3927 weapons[weaponids[weaponactive]].bloody = 2;
3929 weapons[weaponids[weaponactive]].blooddrip += 5;
3933 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3935 victim->velocity = 0;
3936 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3937 victim->skeleton.joints[i].velocity = 0;
3939 if (animTarget == knifefollowanim) {
3941 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3942 victim->skeleton.joints[i].velocity = 0;
3945 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3946 emit_sound_at(fleshstabremovesound, victim->coords);
3948 weapons[weaponids[weaponactive]].bloody = 2;
3950 weapons[weaponids[weaponactive]].blooddrip += 5;
3952 XYZ footvel, footpoint;
3954 footpoint = weapons[weaponids[0]].tippoint;
3956 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3958 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3959 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3960 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3961 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3962 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3966 if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3967 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3968 award_bonus(id, backstab);
3972 XYZ footvel, footpoint;
3974 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3976 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3978 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3979 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3980 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3981 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3982 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3983 victim->DoBloodBig(200, 180);
3984 victim->DoBloodBig(200, 215);
3985 victim->bloodloss += 10000;
3986 victim->velocity = 0;
3987 emit_sound_at(fleshstabsound, victim->coords);
3989 weapons[weaponids[weaponactive]].bloody = 2;
3991 weapons[weaponids[weaponactive]].blooddrip += 5;
3995 if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3997 victim->velocity = 0;
3998 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3999 victim->skeleton.joints[i].velocity = 0;
4001 if (weaponactive != -1) {
4002 emit_sound_at(fleshstabremovesound, victim->coords);
4004 weapons[weaponids[weaponactive]].bloody = 2;
4006 weapons[weaponids[weaponactive]].blooddrip += 5;
4008 XYZ footvel, footpoint;
4010 footpoint = weapons[weaponids[0]].tippoint;
4012 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
4014 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
4015 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
4016 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
4017 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
4018 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
4022 if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
4031 if (weaponactive == -1) {
4032 if (!Tutorial::active) {
4033 emit_sound_at(heavyimpactsound, victim->coords, 128.);
4038 if (weaponactive != -1 || creature == wolftype) {
4041 if (creature == rabbittype && weaponactive != -1) {
4042 if (weapons[weaponids[0]].getType() == staff) {
4047 if (weaponactive != -1) {
4048 victim->DoBloodBig(2 / victim->armorhead, 225);
4049 emit_sound_at(knifeslicesound, victim->coords);
4050 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
4051 weapons[weaponids[weaponactive]].bloody = 1;
4053 weapons[weaponids[weaponactive]].blooddrip += 3;
4055 if (weaponactive == -1 && creature == wolftype) {
4056 emit_sound_at(clawslicesound, victim->coords, 128.);
4058 victim->DoBloodBig(2 / victim->armorhead, 175);
4062 award_bonus(id, Reversal);
4067 relative = facing * -1;
4069 Normalise(&relative);
4070 relative = DoRotation(relative, 0, 90, 0);
4072 Normalise(&relative);
4073 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
4074 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
4076 victim->jointVel(head) += relative * damagemult * 200;
4077 if (victim->damage < victim->damagetolerance - 100) {
4078 victim->velocity = relative * 200;
4080 victim->DoDamage(damagemult * 100 / victim->protectionhead);
4081 victim->velocity = 0;
4084 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))) {
4088 relative = facing * -1;
4090 Normalise(&relative);
4091 relative = DoRotation(relative, 0, 90, 0);
4093 Normalise(&relative);
4094 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
4095 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
4097 victim->jointVel(head) += relative * damagemult * 200;
4100 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim)) {
4101 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
4102 award_bonus(id, reverseko);
4108 if (frameTarget > int(Animation::animations[animCurrent].frames.size()) - 1) {
4111 animTarget = getIdle();
4112 FootLand(leftfoot, 1);
4113 FootLand(rightfoot, 1);
4115 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
4116 animTarget = rollanim;
4118 emit_sound_at(movewhooshsound, coords, 128.);
4120 if (animCurrent == staggerbackhighanim) {
4121 animTarget = getIdle();
4123 if (animCurrent == staggerbackhardanim) {
4124 animTarget = getIdle();
4126 if (animCurrent == removeknifeanim) {
4127 animTarget = getIdle();
4129 if (animCurrent == crouchremoveknifeanim) {
4130 animTarget = getCrouch();
4132 if (animCurrent == backhandspringanim) {
4133 animTarget = getIdle();
4135 if (animCurrent == dodgebackanim) {
4136 animTarget = getIdle();
4138 if (animCurrent == drawleftanim) {
4139 animTarget = getIdle();
4141 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
4142 animTarget = getIdle();
4143 if (animCurrent == crouchdrawrightanim) {
4144 animTarget = getCrouch();
4146 if (weaponactive == -1) {
4148 } else if (weaponactive == 0) {
4150 if (num_weapons == 2) {
4152 buffer = weaponids[0];
4153 weaponids[0] = weaponids[1];
4154 weaponids[1] = buffer;
4158 if (weaponactive == -1) {
4159 emit_sound_at(knifesheathesound, coords, 128.);
4161 if (weaponactive != -1) {
4162 emit_sound_at(knifedrawsound, coords, 128.);
4165 if (animCurrent == rollanim) {
4166 animTarget = getCrouch();
4167 FootLand(leftfoot, 1);
4168 FootLand(rightfoot, 1);
4171 if (animTarget == walljumprightkickanim) {
4174 if (animTarget == walljumpleftkickanim) {
4177 animTarget = jumpdownanim;
4179 if (animCurrent == climbanim) {
4180 animTarget = getCrouch();
4182 coords += facing * .1;
4183 if (!isnormal(coords.x)) {
4194 if (animTarget == rabbitkickreversalanim) {
4195 animTarget = getCrouch();
4198 if (animTarget == jumpreversalanim) {
4199 animTarget = getCrouch();
4202 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
4203 if (attackkeydown && animTarget != walljumpfrontanim) {
4205 float closestdist = -1;
4207 if (Person::players.size() > 1) {
4208 for (unsigned i = 0; i < Person::players.size(); i++) {
4209 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4210 distance = distsq(&Person::players[i]->coords, &coords);
4211 if (closestdist == -1 || distance < closestdist) {
4212 closestdist = distance;
4218 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4219 victim = Person::players[closest];
4220 animTarget = walljumprightkickanim;
4222 XYZ rotatetarget = victim->coords - coords;
4223 Normalise(&rotatetarget);
4224 yaw = -asin(0 - rotatetarget.x);
4226 if (rotatetarget.z < 0) {
4229 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4230 velocity = (victim->coords - coords) * 4;
4235 if (animTarget == walljumpbackanim) {
4236 animTarget = backflipanim;
4238 velocity = facing * -8;
4241 resume_stream(whooshsound);
4244 if (animTarget == walljumprightanim) {
4245 animTarget = rightflipanim;
4249 velocity = DoRotation(facing, 0, 30, 0) * -8;
4252 if (animTarget == walljumpfrontanim) {
4253 animTarget = frontflipanim;
4257 velocity = facing * 8;
4261 resume_stream(whooshsound);
4264 if (animTarget == walljumpleftanim) {
4265 if (attackkeydown) {
4267 float closestdist = -1;
4269 if (Person::players.size() > 1) {
4270 for (unsigned i = 0; i < Person::players.size(); i++) {
4271 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4272 distance = distsq(&Person::players[i]->coords, &coords);
4273 if (closestdist == -1 || distance < closestdist) {
4274 closestdist = distance;
4280 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4281 victim = Person::players[closest];
4282 animTarget = walljumpleftkickanim;
4284 XYZ rotatetarget = victim->coords - coords;
4285 Normalise(&rotatetarget);
4286 yaw = -asin(0 - rotatetarget.x);
4288 if (rotatetarget.z < 0) {
4291 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4292 velocity = (victim->coords - coords) * 4;
4297 if (animTarget != walljumpleftkickanim) {
4298 animTarget = leftflipanim;
4302 velocity = DoRotation(facing, 0, -30, 0) * -8;
4306 resume_stream(whooshsound);
4309 if (animTarget == sneakattackanim) {
4310 animCurrent = getCrouch();
4311 animTarget = getCrouch();
4318 transspeed = 1000000;
4319 targetheadyaw += 180;
4320 coords -= facing * .7;
4322 coords.y = terrain.getHeight(coords.x, coords.z);
4327 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
4328 animTarget = getIdle();
4331 coords.y = terrain.getHeight(coords.x, coords.z);
4336 if (animCurrent == knifefollowanim) {
4337 animTarget = getIdle();
4340 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
4341 float ycoords = oldcoords.y;
4342 animTarget = getStop();
4347 transspeed = 1000000;
4348 targetheadyaw += 180;
4349 if (!isnormal(coords.x)) {
4352 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim) {
4353 oldcoords = coords + facing * .5;
4354 } else if (animCurrent == sweepreversalanim) {
4355 oldcoords = coords + facing * 1.1;
4356 } else if (animCurrent == upunchreversalanim) {
4357 oldcoords = coords + facing * 1.5;
4360 targetheadyaw += 180;
4363 } else if (animCurrent == knifeslashreversalanim) {
4364 oldcoords = coords + facing * .5;
4367 targetheadyaw += 90;
4370 } else if (animCurrent == staffspinhitreversalanim) {
4373 targetheadyaw += 180;
4378 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
4380 oldcoords.y = ycoords;
4382 currentoffset = coords - oldcoords;
4388 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4393 if (Animation::animations[animTarget].attack == reversed) {
4395 if (animTarget == sweepreversedanim) {
4398 animTarget = backhandspringanim;
4400 emit_sound_at(landsound, coords, 128);
4402 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4403 animTarget = rollanim;
4406 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4407 coords.y = oldcoords.y;
4409 if (animCurrent == knifeslashreversedanim) {
4410 animTarget = rollanim;
4415 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4416 coords.y = oldcoords.y;
4420 animTarget = jumpdownanim;
4423 animTarget = getIdle();
4425 if (wasLandhard()) {
4426 animTarget = getIdle();
4428 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4429 animTarget = getIdle();
4431 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4432 coords.y = oldcoords.y;
4433 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4434 targetoffset.y = coords.y;
4436 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4438 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4439 currentoffset.y -= (coords.y - targetoffset.y);
4440 coords.y = targetoffset.y;
4442 normalsupdatedelay = 0;
4444 if (animCurrent == upunchanim) {
4445 animTarget = getStop();
4446 normalsupdatedelay = 0;
4449 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4453 if (num_weapons > 0) {
4454 if (weapons[0].getType() == staff) {
4463 rabbitkickragdoll = 1;
4465 if (animCurrent == rabbitkickreversedanim) {
4471 skeleton.spinny = 0;
4472 SolidHitBonus(!id); // FIXME: tricky id
4476 animTarget = rollanim;
4479 pause_sound(whooshsound);
4484 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4488 skeleton.spinny = 0;
4490 if (animCurrent == jumpreversedanim) {
4496 skeleton.spinny = 0;
4497 SolidHitBonus(!id); // FIXME: tricky id
4501 animTarget = rollanim;
4502 coords += facing * 2;
4504 pause_sound(whooshsound);
4510 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) {
4511 animTarget = getupfromfrontanim;
4513 } else if (Animation::animations[animCurrent].attack == normalattack) {
4514 animTarget = getIdle();
4517 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4518 animTarget = blockhighleftstrikeanim;
4520 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4521 animTarget = getIdle();
4524 if (animCurrent == spinkickanim && victim->skeleton.free) {
4525 if (creature == rabbittype) {
4526 animTarget = fightidleanim;
4532 if (isIdle() && !wasIdle()) {
4533 normalsupdatedelay = 0;
4536 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4537 animTarget = jumpdownanim;
4540 if (!skeleton.free) {
4542 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4543 if (!isRun() || !wasRun()) {
4544 if (targetFrame().speed > currentFrame().speed) {
4545 target += multiplier * targetFrame().speed * speed * 2;
4547 if (targetFrame().speed <= currentFrame().speed) {
4548 target += multiplier * currentFrame().speed * speed * 2;
4551 if (isRun() && wasRun()) {
4553 tempspeed = velspeed;
4554 if (tempspeed < 10 * speedmult) {
4555 tempspeed = 10 * speedmult;
4557 /* FIXME - mixed of target and current here, is that intended? */
4558 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4560 } else if (transspeed) {
4561 target += multiplier * transspeed * speed * 2;
4563 if (!isRun() || !wasRun()) {
4564 if (targetFrame().speed > currentFrame().speed) {
4565 target += multiplier * targetFrame().speed * 2;
4567 if (targetFrame().speed <= currentFrame().speed) {
4568 target += multiplier * currentFrame().speed * 2;
4573 if (animCurrent != animTarget) {
4574 target = (target + oldtarget) / 2;
4578 frameCurrent = frameTarget;
4582 rot = targetrot * target;
4583 yaw += rot - oldrot;
4589 if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
4590 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4592 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4594 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4595 skeleton.joints[i].position = currentFrame().joints[i].position;
4598 skeleton.FindForwards();
4600 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4601 if (skeleton.muscles[i].visible) {
4602 skeleton.FindRotationMuscle(i, animTarget);
4605 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4606 if (skeleton.muscles[i].visible) {
4607 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4608 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4610 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4611 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4613 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4614 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4620 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4621 skeleton.joints[i].position = targetFrame().joints[i].position;
4624 skeleton.FindForwards();
4626 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4627 if (skeleton.muscles[i].visible) {
4628 skeleton.FindRotationMuscle(i, animTarget);
4631 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4632 if (skeleton.muscles[i].visible) {
4633 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4634 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4636 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4637 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4639 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4640 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4642 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) {
4643 skeleton.muscles[i].newrotate3 -= 360;
4645 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) {
4646 skeleton.muscles[i].newrotate3 += 360;
4648 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) {
4649 skeleton.muscles[i].newrotate2 -= 360;
4651 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) {
4652 skeleton.muscles[i].newrotate2 += 360;
4654 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) {
4655 skeleton.muscles[i].newrotate1 -= 360;
4657 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) {
4658 skeleton.muscles[i].newrotate1 += 360;
4664 oldanimCurrent = animCurrent;
4665 oldanimTarget = animTarget;
4666 oldframeTarget = frameTarget;
4667 oldframeCurrent = frameCurrent;
4669 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4670 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target - skeleton.joints[i].position) / multiplier;
4671 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target;
4673 offset = currentoffset * (1 - target) + targetoffset * target;
4674 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4675 if (skeleton.muscles[i].visible) {
4676 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * target;
4677 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * target;
4678 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * target;
4683 if (isLanding() && landhard) {
4687 animTarget = getLandhard();
4700 void Person::DoStuff()
4702 static XYZ terrainnormal;
4703 static XYZ flatfacing;
4704 static XYZ flatvelocity;
4705 static float flatvelspeed;
4706 static int bloodsize;
4707 static int startx, starty, endx, endy;
4708 static GLubyte color;
4709 static XYZ bloodvel;
4711 onfiredelay -= multiplier;
4712 if (onfiredelay < 0 && onfire) {
4713 if (Random() % 2 == 0) {
4719 crouchkeydowntime += multiplier;
4720 if (!crouchkeydown) {
4721 crouchkeydowntime = 0;
4723 jumpkeydowntime += multiplier;
4724 if (!jumpkeydown && skeleton.free) {
4725 jumpkeydowntime = 0;
4728 if (hostile || damage > 0 || bloodloss > 0) {
4732 if (isIdle() || isRun()) {
4736 if (num_weapons == 1 && weaponactive != -1) {
4741 blooddimamount -= multiplier * .3;
4743 speechdelay -= multiplier;
4744 texupdatedelay -= multiplier;
4745 interestdelay -= multiplier;
4746 flamedelay -= multiplier;
4747 parriedrecently -= multiplier;
4749 victim = this->shared_from_this();
4754 speed = 1.1 * speedmult;
4756 speed = 1.0 * speedmult;
4758 if (!skeleton.free) {
4759 rabbitkickragdoll = 0;
4764 if (id != 0 && (creature == rabbittype || difficulty != 2)) {
4767 if (id != 0 && creature == wolftype && difficulty == 2) {
4769 if (aitype != passivetype) {
4771 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) {
4778 if (animTarget == wolfrunninganim && !superruntoggle) {
4779 animTarget = getRun();
4783 if (weaponactive == -1 && num_weapons > 0) {
4784 if (weapons[weaponids[0]].getType() == staff) {
4790 burnt += multiplier;
4795 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4797 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4804 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
4805 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4809 while (flamedelay < 0 && onfire) {
4811 int howmany = fabs(Random() % (skeleton.joints.size()));
4812 if (skeleton.free) {
4813 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4814 flatfacing = skeleton.joints[howmany].position * scale + coords;
4816 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4817 flatvelocity = (coords - oldcoords) / multiplier / 2;
4819 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4822 while (flamedelay < 0 && !onfire && Tutorial::active && id != 0) {
4824 int howmany = fabs(Random() % (skeleton.joints.size()));
4825 if (skeleton.free) {
4826 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4827 flatfacing = skeleton.joints[howmany].position * scale + coords;
4829 flatvelocity = (coords - oldcoords) / multiplier / 2;
4830 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4832 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4836 bleeding -= multiplier * .3;
4837 if (bloodtoggle == 2) {
4838 skeleton.drawmodel.textureptr.bind();
4839 if ((bleeding <= 0) && (detail != 2)) {
4845 if (neckspurtamount > 0) {
4846 neckspurtamount -= multiplier;
4847 neckspurtdelay -= multiplier * 3;
4848 neckspurtparticledelay -= multiplier * 3;
4849 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4852 if (skeleton.free) {
4853 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4854 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4855 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4857 bloodvel.z = 5 * neckspurtamount;
4858 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4859 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4860 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4862 neckspurtparticledelay = .05;
4864 if (neckspurtdelay < 0) {
4869 if (deathbleeding > 0 && dead != 2) {
4870 if (deathbleeding < 5) {
4871 bleeddelay -= deathbleeding * multiplier / 4;
4873 bleeddelay -= 5 * multiplier / 4;
4875 if (bleeddelay < 0 && bloodtoggle) {
4880 if (skeleton.free) {
4881 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4882 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4884 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4885 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4889 bloodloss += deathbleeding * multiplier * 80;
4890 deathbleeding -= multiplier * 1.6;
4891 if (deathbleeding < 0) {
4894 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4895 if (weaponactive != -1) {
4896 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4897 weapons[weaponids[0]].velocity.x += .01;
4900 weaponids[0] = weaponids[num_weapons];
4901 if (weaponstuck == num_weapons) {
4906 for (unsigned i = 0; i < Person::players.size(); i++) {
4907 Person::players[i]->wentforweapon = 0;
4915 if (!dead && creature == wolftype) {
4916 award_bonus(0, Wolfbonus);
4919 if (animTarget == knifefollowedanim && !skeleton.free) {
4920 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4921 skeleton.joints[i].velocity = 0;
4922 skeleton.joints[i].velocity.y = -2;
4925 if (id != 0 && unconscioustime > .1) {
4933 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4934 texupdatedelay = .12;
4936 bloodsize = 5 - realtexdetail;
4940 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4941 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4942 endx = startx + bloodsize;
4943 endy = starty + bloodsize;
4953 if (endx > skeleton.skinsize - 1) {
4954 endx = skeleton.skinsize - 1;
4957 if (endy > skeleton.skinsize - 1) {
4958 endy = skeleton.skinsize - 1;
4961 if (endx < startx) {
4964 if (endy < starty) {
4968 for (int i = startx; i < endx; i++) {
4969 for (int j = starty; j < endy; j++) {
4970 if (Random() % 2 == 0) {
4971 color = Random() % 85 + 170;
4972 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2) {
4973 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4975 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4976 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4981 skeleton.drawmodel.textureptr.bind();
4985 if (skeleton.free) {
4986 bleedx += 4 * direction / realtexdetail;
4988 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4990 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4993 bleedy -= 4 / realtexdetail;
4995 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4997 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
5002 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
5003 righthandmorphness = targetrighthandmorphness;
5004 righthandmorphstart = righthandmorphend;
5005 } else if (righthandmorphness > targetrighthandmorphness) {
5006 righthandmorphness -= multiplier * 4;
5007 } else if (righthandmorphness < targetrighthandmorphness) {
5008 righthandmorphness += multiplier * 4;
5011 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
5012 lefthandmorphness = targetlefthandmorphness;
5013 lefthandmorphstart = lefthandmorphend;
5014 } else if (lefthandmorphness > targetlefthandmorphness) {
5015 lefthandmorphness -= multiplier * 4;
5016 } else if (lefthandmorphness < targetlefthandmorphness) {
5017 lefthandmorphness += multiplier * 4;
5020 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
5021 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
5022 tailmorphness = targettailmorphness;
5023 tailmorphstart = tailmorphend;
5024 } else if (tailmorphness > targettailmorphness) {
5025 tailmorphness -= multiplier * 10;
5026 } else if (tailmorphness < targettailmorphness) {
5027 tailmorphness += multiplier * 10;
5031 if (creature == wolftype) {
5032 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
5033 tailmorphness = targettailmorphness;
5034 tailmorphstart = tailmorphend;
5035 } else if (tailmorphness > targettailmorphness) {
5036 tailmorphness -= multiplier * 2;
5037 } else if (tailmorphness < targettailmorphness) {
5038 tailmorphness += multiplier * 2;
5042 if (headmorphend == 3 || headmorphstart == 3) {
5043 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
5044 headmorphness = targetheadmorphness;
5045 headmorphstart = headmorphend;
5046 } else if (headmorphness > targetheadmorphness) {
5047 headmorphness -= multiplier * 7;
5048 } else if (headmorphness < targetheadmorphness) {
5049 headmorphness += multiplier * 7;
5051 } else if (headmorphend == 5 || headmorphstart == 5) {
5052 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
5053 headmorphness = targetheadmorphness;
5054 headmorphstart = headmorphend;
5055 } else if (headmorphness > targetheadmorphness) {
5056 headmorphness -= multiplier * 10;
5057 } else if (headmorphness < targetheadmorphness) {
5058 headmorphness += multiplier * 10;
5061 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
5062 headmorphness = targetheadmorphness;
5063 headmorphstart = headmorphend;
5064 } else if (headmorphness > targetheadmorphness) {
5065 headmorphness -= multiplier * 4;
5066 } else if (headmorphness < targetheadmorphness) {
5067 headmorphness += multiplier * 4;
5071 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
5072 chestmorphness = targetchestmorphness;
5073 chestmorphstart = chestmorphend;
5074 } else if (chestmorphness > targetchestmorphness) {
5075 chestmorphness -= multiplier;
5076 } else if (chestmorphness < targetchestmorphness) {
5077 chestmorphness += multiplier;
5080 if (dead != 2 && howactive <= typesleeping) {
5081 if (chestmorphstart == 0 && chestmorphend == 0) {
5083 targetchestmorphness = 1;
5086 if (chestmorphstart != 0 && chestmorphend != 0) {
5088 targetchestmorphness = 1;
5090 if (environment == snowyenvironment) {
5093 if (skeleton.free) {
5094 footvel = skeleton.specialforward[0] * -1;
5095 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
5097 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
5098 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
5100 if (animTarget == sleepanim) {
5101 footvel = DoRotation(footvel, 0, 90, 0);
5103 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
5107 if (!dead && howactive < typesleeping) {
5108 blinkdelay -= multiplier * 2;
5109 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
5111 targetheadmorphness = 1;
5113 blinkdelay = (float)(abs(Random() % 40)) / 5;
5115 if (headmorphstart == 3 && headmorphend == 3) {
5117 targetheadmorphness = 1;
5122 twitchdelay -= multiplier * 1.5;
5123 if (animTarget != hurtidleanim) {
5124 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
5126 targetheadmorphness = 1;
5128 twitchdelay = (float)(abs(Random() % 40)) / 5;
5130 if (headmorphstart == 5 && headmorphend == 5) {
5132 targetheadmorphness = 1;
5136 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
5137 twitchdelay3 -= multiplier * 1;
5138 if (Random() % 2 == 0) {
5139 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
5140 righthandmorphness = 0;
5141 targetrighthandmorphness = 1;
5142 righthandmorphend = 1;
5143 if (Random() % 2 == 0) {
5144 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
5147 if (righthandmorphstart == 1 && righthandmorphend == 1) {
5148 righthandmorphness = 0;
5149 targetrighthandmorphness = 1;
5150 righthandmorphend = 0;
5153 if (Random() % 2 == 0) {
5154 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
5155 lefthandmorphness = 0;
5156 targetlefthandmorphness = 1;
5157 lefthandmorphend = 1;
5158 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
5160 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
5161 lefthandmorphness = 0;
5162 targetlefthandmorphness = 1;
5163 lefthandmorphend = 0;
5169 if (creature == rabbittype) {
5170 if (howactive < typesleeping) {
5171 twitchdelay2 -= multiplier * 1.5;
5173 twitchdelay2 -= multiplier * 0.5;
5175 if (howactive <= typesleeping) {
5176 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
5178 targettailmorphness = 1;
5180 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
5182 if (tailmorphstart == 1 && tailmorphend == 1) {
5184 targettailmorphness = 1;
5187 if (tailmorphstart == 2 && tailmorphend == 2) {
5189 targettailmorphness = 1;
5196 if (creature == wolftype) {
5197 twitchdelay2 -= multiplier * 1.5;
5198 if (tailmorphend != 0) {
5199 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
5201 targettailmorphness = 1;
5206 if (tailmorphend != 5) {
5207 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
5209 targettailmorphness = 1;
5214 if (twitchdelay2 <= 0) {
5215 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
5217 targettailmorphness = 1;
5220 if (tailmorphstart == 1 && tailmorphend == 1) {
5222 targettailmorphness = 1;
5225 if (tailmorphstart == 2 && tailmorphend == 2) {
5227 targettailmorphness = 1;
5230 if (tailmorphstart == 3 && tailmorphend == 3) {
5232 targettailmorphness = 1;
5235 if (tailmorphstart == 4 && tailmorphend == 4) {
5237 targettailmorphness = 1;
5244 unconscioustime = 0;
5247 if (dead == 1 || howactive == typesleeping) {
5248 unconscioustime += multiplier;
5249 //If unconscious, close eyes and mouth
5250 if (righthandmorphend != 0) {
5251 righthandmorphness = 0;
5253 righthandmorphend = 0;
5254 targetrighthandmorphness = 1;
5256 if (lefthandmorphend != 0) {
5257 lefthandmorphness = 0;
5259 lefthandmorphend = 0;
5260 targetlefthandmorphness = 1;
5262 if (headmorphend != 3 && headmorphend != 5) {
5266 targetheadmorphness = 1;
5269 if (howactive > typesleeping) {
5272 if (bloodtoggle && !bled) {
5273 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5274 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5275 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5276 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5280 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5286 if (dead == 2 || howactive > typesleeping) {
5287 //If dead, open mouth and hands
5288 if (righthandmorphend != 0) {
5289 righthandmorphness = 0;
5291 righthandmorphend = 0;
5292 targetrighthandmorphness = 1;
5294 if (lefthandmorphend != 0) {
5295 lefthandmorphness = 0;
5297 lefthandmorphend = 0;
5298 targetlefthandmorphness = 1;
5300 if (headmorphend != 2) {
5304 targetheadmorphness = 1;
5307 if (stunned > 0 && !dead && headmorphend != 2) {
5308 if (headmorphend != 4) {
5312 targetheadmorphness = 1;
5315 if (damage > damagetolerance && !dead) {
5318 unconscioustime = 0;
5320 if (creature == wolftype) {
5321 award_bonus(0, Wolfbonus);
5326 if (weaponactive != -1) {
5327 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5328 weapons[weaponids[0]].velocity.x += .01;
5331 weaponids[0] = weaponids[num_weapons];
5332 if (weaponstuck == num_weapons) {
5337 for (unsigned i = 0; i < Person::players.size(); i++) {
5338 Person::players[i]->wentforweapon = 0;
5342 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
5351 damage -= multiplier * 13;
5352 permanentdamage -= multiplier * 4;
5353 if (isIdle() || isCrouch()) {
5354 permanentdamage -= multiplier * 4;
5360 if (permanentdamage < 0) {
5361 permanentdamage = 0;
5363 if (superpermanentdamage < 0) {
5364 superpermanentdamage = 0;
5366 if (permanentdamage < superpermanentdamage) {
5367 permanentdamage = superpermanentdamage;
5369 if (damage < permanentdamage) {
5370 damage = permanentdamage;
5372 if (dead == 1 && damage < damagetolerance) {
5376 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5377 skeleton.joints[i].velocity = 0;
5380 if (permanentdamage > damagetolerance && dead != 2) {
5383 if (weaponactive != -1) {
5384 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5385 weapons[weaponids[0]].velocity.x += .01;
5388 weaponids[0] = weaponids[num_weapons];
5389 if (weaponstuck == num_weapons) {
5394 for (unsigned i = 0; i < Person::players.size(); i++) {
5395 Person::players[i]->wentforweapon = 0;
5401 if (!dead && creature == wolftype) {
5402 award_bonus(0, Wolfbonus);
5405 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance) {
5406 award_bonus(id, touchofdeath);
5408 if (id != 0 && unconscioustime > .1) {
5416 emit_sound_at(breaksound, coords);
5419 if (skeleton.free == 1) {
5421 pause_sound(whooshsound);
5425 //If knocked over, open hands and close mouth
5426 if (righthandmorphend != 0) {
5427 righthandmorphness = 0;
5429 righthandmorphend = 0;
5430 targetrighthandmorphness = 1;
5432 if (lefthandmorphend != 0) {
5433 lefthandmorphness = 0;
5435 lefthandmorphend = 0;
5436 targetlefthandmorphness = 1;
5438 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
5439 if (headmorphend != 0) {
5443 targetheadmorphness = 1;
5447 skeleton.DoGravity(&scale);
5449 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
5450 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1)) {
5451 award_bonus(id, deepimpact);
5453 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5457 if (!skeleton.joints.empty()) {
5458 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5459 average += skeleton.joints[j].position;
5461 average /= skeleton.joints.size();
5462 coords += average * scale;
5463 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5464 skeleton.joints[j].position -= average;
5466 average /= multiplier;
5470 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5471 velocity += skeleton.joints[i].velocity * scale;
5473 velocity /= skeleton.joints.size();
5475 if (!isnormal(velocity.x) && velocity.x) {
5479 if (findLength(&average) < 10 && dead && skeleton.free) {
5480 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5481 if (skeleton.longdead > 2000) {
5482 if (skeleton.longdead > 6000) {
5484 pause_sound(whooshsound);
5490 if (dead == 2 && bloodloss < damagetolerance) {
5492 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5494 if (bloodtoggle && !bled) {
5495 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5496 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5497 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5498 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5499 float size = .2 * 1.2;
5502 Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5507 if (dead == 2 && bloodloss >= damagetolerance) {
5509 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5510 if (bleeding <= 0) {
5513 if (bloodtoggle && !bled) {
5514 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5515 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5516 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5517 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5521 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5529 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5530 bool canrecover = 1;
5531 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5532 startpoint = coords;
5535 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1) {
5538 if (velocity.y < -30) {
5541 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5542 if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) {
5543 colviewer = startpoint;
5544 coltarget = endpoint;
5545 if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1) {
5555 terrainnormal = jointPos(groin) - jointPos(abdomen);
5556 if (joint(groin).locked && joint(abdomen).locked) {
5557 terrainnormal = jointPos(groin) - jointPos(abdomen);
5558 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5560 if (joint(abdomen).locked && joint(neck).locked) {
5561 terrainnormal = jointPos(abdomen) - jointPos(neck);
5562 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5564 if (joint(groin).locked && joint(neck).locked) {
5565 terrainnormal = jointPos(groin) - jointPos(neck);
5566 middle = (jointPos(groin) + jointPos(neck)) / 2;
5568 Normalise(&terrainnormal);
5570 targetyaw = -asin(0 - terrainnormal.x);
5571 targetyaw *= 360 / 6.28;
5572 if (terrainnormal.z < 0) {
5573 targetyaw = 180 - targetyaw;
5578 animTarget = flipanim;
5579 crouchtogglekeydown = 1;
5584 animCurrent = tempanim;
5588 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5589 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5590 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5595 if (findLength(&average) < 10 && !dead && skeleton.free) {
5596 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5597 if (skeleton.longdead > (damage + 500) * 1.5) {
5599 pause_sound(whooshsound);
5606 terrainnormal = jointPos(groin) - jointPos(abdomen);
5607 if (joint(groin).locked && joint(abdomen).locked) {
5608 terrainnormal = jointPos(groin) - jointPos(abdomen);
5609 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5611 if (joint(abdomen).locked && joint(neck).locked) {
5612 terrainnormal = jointPos(abdomen) - jointPos(neck);
5613 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5615 if (joint(groin).locked && joint(neck).locked) {
5616 terrainnormal = jointPos(groin) - jointPos(neck);
5617 middle = (jointPos(groin) + jointPos(neck)) / 2;
5619 Normalise(&terrainnormal);
5621 targetyaw = -asin(0 - terrainnormal.x);
5622 targetyaw *= 360 / 6.28;
5623 if (terrainnormal.z < 0) {
5624 targetyaw = 180 - targetyaw;
5628 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5630 if (skeleton.forward.y < 0) {
5631 animTarget = getupfrombackanim;
5635 if (skeleton.forward.y > -.3) {
5636 animTarget = getupfromfrontanim;
5644 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5645 animTarget = rollanim;
5646 targetyaw = lookyaw;
5650 if (forwardkeydown) {
5659 if (forwardkeydown) {
5667 if (!leftkeydown && !rightkeydown) {
5675 if (abs(targettilt2) > 50) {
5678 animCurrent = tempanim;
5681 tilt2 = targettilt2;
5683 if (middle.y > 0 && animTarget != rollanim) {
5684 targetoffset.y = middle.y + 1;
5687 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5688 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5689 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5696 if (num_weapons > 0) {
5697 if (weapons[0].getType() == staff) {
5701 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5702 if (velocity.y > -30) {
5704 tempvelocity = velocity;
5705 Normalise(&tempvelocity);
5706 targetyaw = -asin(0 - tempvelocity.x);
5707 targetyaw *= 360 / 6.28;
5708 if (velocity.z < 0) {
5709 targetyaw = 180 - targetyaw;
5714 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5715 animTarget = rollanim;
5718 animTarget = backhandspringanim;
5724 emit_sound_at(movewhooshsound, coords, 128.);
5726 animCurrent = animTarget;
5727 frameCurrent = frameTarget - 1;
5739 if (skeleton.freefall == 0) {
5744 if (aitype != passivetype || skeleton.free == 1) {
5745 if (findLengthfast(&velocity) > .1) {
5746 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5747 if (Object::objects[i]->type == firetype) {
5748 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) {
5750 if (!Object::objects[i]->onfire) {
5751 emit_sound_at(firestartsound, Object::objects[i]->position);
5753 Object::objects[i]->onfire = 1;
5756 if (Object::objects[i]->onfire) {
5762 if (Object::objects[i]->type == bushtype) {
5763 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) {
5765 if (!Object::objects[i]->onfire) {
5766 emit_sound_at(firestartsound, Object::objects[i]->position);
5768 Object::objects[i]->onfire = 1;
5772 if (Object::objects[i]->onfire) {
5776 if (Object::objects[i]->messedwith <= 0) {
5780 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5783 addEnvSound(coords, 4 * findLength(&velocity));
5787 if (environment == grassyenvironment) {
5788 howmany = findLength(&velocity) * 4;
5790 if (environment == snowyenvironment) {
5791 howmany = findLength(&velocity) * 2;
5794 if (environment != desertenvironment) {
5795 for (int j = 0; j < howmany; j++) {
5796 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5797 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5798 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5801 pos.x += float(abs(Random() % 100) - 50) / 200;
5802 pos.y += float(abs(Random() % 100) - 50) / 200;
5803 pos.z += float(abs(Random() % 100) - 50) / 200;
5804 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);
5805 Sprite::setLastSpriteSpecial(1);
5809 howmany = findLength(&velocity) * 4;
5811 if (environment == snowyenvironment) {
5812 for (int j = 0; j < howmany; j++) {
5813 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5814 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5815 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5818 pos.x += float(abs(Random() % 100) - 50) / 200;
5819 pos.y += float(abs(Random() % 100) - 50) / 200;
5820 pos.z += float(abs(Random() % 100) - 50) / 200;
5821 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5822 Sprite::setLastSpriteSpecial(2);
5827 Object::objects[i]->rotx += velocity.x * multiplier * 6;
5828 Object::objects[i]->roty += velocity.z * multiplier * 6;
5829 Object::objects[i]->messedwith = .5;
5833 if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) {
5834 if (Object::objects[i]->pitch == 0) {
5837 tempcoord = coords - Object::objects[i]->position;
5838 tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0);
5839 tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0);
5840 tempcoord += Object::objects[i]->position;
5842 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) {
5843 if (Object::objects[i]->messedwith <= 0) {
5847 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5850 addEnvSound(coords, 4 * findLength(&velocity));
5854 if (environment == grassyenvironment) {
5855 howmany = findLength(&velocity) * 4;
5857 if (environment == snowyenvironment) {
5858 howmany = findLength(&velocity) * 2;
5861 if (environment != desertenvironment) {
5862 for (int j = 0; j < howmany; j++) {
5863 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5864 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5865 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5867 pos += velocity * .1;
5869 pos.x += float(abs(Random() % 100) - 50) / 150;
5870 pos.y += float(abs(Random() % 100) - 50) / 150;
5871 pos.z += float(abs(Random() % 100) - 50) / 150;
5872 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);
5873 Sprite::setLastSpriteSpecial(1);
5877 howmany = findLength(&velocity) * 4;
5879 if (environment == snowyenvironment) {
5880 for (int j = 0; j < howmany; j++) {
5881 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5882 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5883 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5885 pos += velocity * .1;
5887 pos.x += float(abs(Random() % 100) - 50) / 150;
5888 pos.y += float(abs(Random() % 100) - 50) / 150;
5889 pos.z += float(abs(Random() % 100) - 50) / 150;
5890 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5891 Sprite::setLastSpriteSpecial(2);
5896 Object::objects[i]->messedwith = .5;
5903 if (!skeleton.free) {
5906 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype) {
5910 if (aitype != passivetype && victim->skeleton.free && !victim->dead) {
5914 if (Tutorial::active && id != 0) {
5917 if (play && aitype != playercontrolled) {
5918 int whichsound = -1;
5919 if (speechdelay <= 0) {
5920 unsigned int i = abs(Random() % 4);
5921 if (creature == rabbittype) {
5923 whichsound = rabbitchitter;
5926 whichsound = rabbitchitter2;
5929 if (creature == wolftype) {
5931 whichsound = growlsound;
5934 whichsound = growl2sound;
5940 if (whichsound != -1) {
5941 emit_sound_at(whichsound, coords);
5945 if (animTarget == staggerbackhighanim) {
5948 if (animTarget == staggerbackhardanim) {
5951 staggerdelay -= multiplier;
5952 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
5955 if (velocity.y < -30 && animTarget == jumpdownanim) {
5958 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5959 animTarget = getIdle();
5963 weaponmissdelay -= multiplier;
5964 highreversaldelay -= multiplier;
5965 lowreversaldelay -= multiplier;
5966 lastcollide -= multiplier;
5967 skiddelay -= multiplier;
5968 if (!isnormal(velocity.x) && velocity.x) {
5971 if (!isnormal(targettilt) && targettilt) {
5974 if (!isnormal(targettilt2) && targettilt2) {
5977 if (!isnormal(targetyaw) && targetyaw) {
5981 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5982 //open hands and close mouth
5983 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5984 righthandmorphness = 0;
5985 righthandmorphend = 0;
5986 targetrighthandmorphness = 1;
5989 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5990 lefthandmorphness = 0;
5991 lefthandmorphend = 0;
5992 targetlefthandmorphness = 1;
5995 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5998 targetheadmorphness = 1;
6002 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) {
6003 //open hands and mouth
6004 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
6005 righthandmorphness = 0;
6006 righthandmorphend = 0;
6007 targetrighthandmorphness = 1;
6010 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
6011 lefthandmorphness = 0;
6012 lefthandmorphend = 0;
6013 targetlefthandmorphness = 1;
6016 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
6019 targetheadmorphness = 1;
6023 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
6024 //close hands and mouth
6025 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
6026 righthandmorphness = 0;
6027 righthandmorphend = 1;
6028 targetrighthandmorphness = 1;
6031 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
6032 lefthandmorphness = 0;
6033 lefthandmorphend = 1;
6034 targetlefthandmorphness = 1;
6037 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
6040 targetheadmorphness = 1;
6044 if (animTarget == spinkickanim ||
6045 animTarget == staffspinhitreversalanim ||
6046 animTarget == staffspinhitreversedanim ||
6047 animTarget == staffhitreversalanim ||
6048 animTarget == staffhitreversedanim ||
6049 animTarget == hurtidleanim ||
6050 animTarget == winduppunchanim ||
6051 animTarget == swordslashreversalanim ||
6052 animTarget == swordslashreversedanim ||
6053 animTarget == knifeslashreversalanim ||
6054 animTarget == knifeslashreversedanim ||
6055 animTarget == knifethrowanim ||
6056 animTarget == knifefollowanim ||
6057 animTarget == knifefollowedanim ||
6058 animTarget == killanim ||
6059 animTarget == dropkickanim ||
6060 animTarget == upunchanim ||
6061 animTarget == knifeslashstartanim ||
6062 animTarget == swordslashanim ||
6063 animTarget == staffhitanim ||
6064 animTarget == staffspinhitanim ||
6065 animTarget == staffgroundsmashanim ||
6066 animTarget == spinkickreversalanim ||
6067 animTarget == sweepreversalanim ||
6068 animTarget == lowkickanim ||
6069 animTarget == sweepreversedanim ||
6070 animTarget == rabbitkickreversalanim ||
6071 animTarget == rabbitkickreversedanim ||
6072 animTarget == jumpreversalanim ||
6073 animTarget == jumpreversedanim) {
6074 //close hands and yell
6075 if (righthandmorphend != 1 &&
6076 righthandmorphness == targetrighthandmorphness) {
6077 righthandmorphness = 0;
6078 righthandmorphend = 1;
6079 targetrighthandmorphness = 1;
6082 if (lefthandmorphend != 1 &&
6083 lefthandmorphness == targetlefthandmorphness) {
6084 lefthandmorphness = 0;
6085 lefthandmorphend = 1;
6086 targetlefthandmorphness = 1;
6089 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
6092 targetheadmorphness = 1;
6099 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
6100 (victim->aitype != searchtype) && (aitype != passivetype) &&
6101 (aitype != searchtype) && (victim->id < Person::players.size())) {
6102 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
6106 if (!dead && animTarget != hurtidleanim) {
6107 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
6108 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
6111 targetheadmorphness = 1;
6116 if (weaponactive != -1) {
6117 if (weapons[weaponids[weaponactive]].getType() != staff) {
6118 righthandmorphstart = 1;
6119 righthandmorphend = 1;
6121 if (weapons[weaponids[weaponactive]].getType() == staff) {
6122 righthandmorphstart = 2;
6123 righthandmorphend = 2;
6125 targetrighthandmorphness = 1;
6128 terrainnormal = terrain.getNormal(coords.x, coords.z);
6130 if (Animation::animations[animTarget].attack != reversal) {
6131 if (!isnormal(coords.x)) {
6140 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
6141 facing = flatfacing;
6142 ReflectVector(&facing, terrainnormal);
6146 animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
6148 targettilt2 = -facing.y * 20;
6154 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim) {
6157 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6158 flatvelocity = velocity;
6160 flatvelspeed = findLength(&flatvelocity);
6161 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
6162 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
6163 if (velocity.y < 0) {
6166 if (velocity.y < 0) {
6169 if (targettilt > 25) {
6172 if (targettilt < -25) {
6177 if (targettilt2 > 45) {
6180 if (targettilt2 < -45) {
6183 if (abs(tilt2 - targettilt2) < multiplier * 400) {
6184 tilt2 = targettilt2;
6185 } else if (tilt2 > targettilt2) {
6186 tilt2 -= multiplier * 400;
6187 } else if (tilt2 < targettilt2) {
6188 tilt2 += multiplier * 400;
6190 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
6199 if (!isnormal(targettilt) && targettilt) {
6202 if (!isnormal(targettilt2) && targettilt2) {
6207 if (animTarget == rabbittackleanim) {
6208 velocity += facing * multiplier * speed * 700 * scale;
6209 velspeed = findLength(&velocity);
6210 if (velspeed > speed * 65 * scale) {
6211 velocity /= velspeed;
6212 velspeed = speed * 65 * scale;
6213 velocity *= velspeed;
6215 velocity.y += gravity * multiplier * 20;
6216 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6217 velspeed = findLength(&velocity);
6218 velocity = flatfacing * velspeed;
6220 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
6221 if (isRun() || animTarget == rabbitkickanim) {
6222 velocity += facing * multiplier * speed * 700 * scale;
6223 velspeed = findLength(&velocity);
6224 if (velspeed > speed * 45 * scale) {
6225 velocity /= velspeed;
6226 velspeed = speed * 45 * scale;
6227 velocity *= velspeed;
6229 velocity.y += gravity * multiplier * 20;
6230 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6231 velspeed = findLength(&velocity);
6232 if (velspeed < speed * 30 * scale) {
6233 velspeed = speed * 30 * scale;
6235 velocity = flatfacing * velspeed;
6237 } else if (isRun()) {
6238 velocity += facing * multiplier * speed * 700 * scale;
6239 velspeed = findLength(&velocity);
6240 if (creature == rabbittype) {
6241 if (velspeed > speed * 55 * scale) {
6242 velocity /= velspeed;
6243 velspeed = speed * 55 * scale;
6244 velocity *= velspeed;
6247 if (creature == wolftype) {
6248 if (velspeed > speed * 75 * scale) {
6249 velocity /= velspeed;
6250 velspeed = speed * 75 * scale;
6251 velocity *= velspeed;
6254 velocity.y += gravity * multiplier * 20;
6255 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6256 velspeed = findLength(&velocity);
6257 velocity = flatfacing * velspeed;
6260 if (animTarget == rollanim && targetFrame().label != 6) {
6261 velocity += facing * multiplier * speed * 700 * scale;
6262 velspeed = findLength(&velocity);
6263 if (velspeed > speed * 45 * scale) {
6264 velocity /= velspeed;
6265 velspeed = speed * 45 * scale;
6266 velocity *= velspeed;
6268 velocity.y += gravity * multiplier * 20;
6269 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6270 velspeed = findLength(&velocity);
6271 velocity = flatfacing * velspeed;
6274 if (animTarget == sneakanim || animTarget == walkanim) {
6275 velocity += facing * multiplier * speed * 700 * scale;
6276 velspeed = findLength(&velocity);
6277 if (velspeed > speed * 12 * scale) {
6278 velocity /= velspeed;
6279 velspeed = speed * 12 * scale;
6280 velocity *= velspeed;
6282 velocity.y += gravity * multiplier * 20;
6283 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6284 velspeed = findLength(&velocity);
6285 velocity = flatfacing * velspeed;
6288 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
6289 velocity += facing * multiplier * speed * 700 * scale;
6290 velspeed = findLength(&velocity);
6291 if (velspeed > speed * 2 * scale) {
6292 velocity /= velspeed;
6293 velspeed = speed * 2 * scale;
6294 velocity *= velspeed;
6296 velocity.y += gravity * multiplier * 20;
6297 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6298 velspeed = findLength(&velocity);
6299 velocity = flatfacing * velspeed;
6302 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
6303 velocity -= facing * multiplier * speed * 700 * scale;
6304 velspeed = findLength(&velocity);
6305 if (velspeed > speed * 2 * scale) {
6306 velocity /= velspeed;
6307 velspeed = speed * 2 * scale;
6308 velocity *= velspeed;
6310 velocity.y += gravity * multiplier * 20;
6311 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6312 velspeed = findLength(&velocity);
6313 velocity = flatfacing * velspeed * -1;
6316 if (animTarget == fightsidestep) {
6317 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
6318 velspeed = findLength(&velocity);
6319 if (velspeed > speed * 12 * scale) {
6320 velocity /= velspeed;
6321 velspeed = speed * 12 * scale;
6322 velocity *= velspeed;
6324 velocity.y += gravity * multiplier * 20;
6325 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6326 velspeed = findLength(&velocity);
6327 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
6330 if (animTarget == staggerbackhighanim) {
6331 coords -= facing * multiplier * speed * 16 * scale;
6334 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
6335 coords -= facing * multiplier * speed * 20 * scale;
6339 if (animTarget == backhandspringanim) {
6340 //coords-=facing*multiplier*50*scale;
6341 velocity += facing * multiplier * speed * 700 * scale * -1;
6342 velspeed = findLength(&velocity);
6343 if (velspeed > speed * 50 * scale) {
6344 velocity /= velspeed;
6345 velspeed = speed * 50 * scale;
6346 velocity *= velspeed;
6348 velocity.y += gravity * multiplier * 20;
6349 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6350 velspeed = findLength(&velocity);
6351 velocity = flatfacing * velspeed * -1;
6353 if (animTarget == dodgebackanim) {
6354 //coords-=facing*multiplier*50*scale;
6355 velocity += facing * multiplier * speed * 700 * scale * -1;
6356 velspeed = findLength(&velocity);
6357 if (velspeed > speed * 60 * scale) {
6358 velocity /= velspeed;
6359 velspeed = speed * 60 * scale;
6360 velocity *= velspeed;
6362 velocity.y += gravity * multiplier * 20;
6363 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6364 velspeed = findLength(&velocity);
6365 velocity = flatfacing * velspeed * -1;
6368 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6369 velspeed = findLength(&velocity);
6372 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6373 velocity.y += gravity * multiplier;
6376 if (animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6377 coords += velocity * multiplier;
6380 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6381 if (isFlip() && targetFrame().label == 7) {
6385 if (animTarget == jumpupanim) {
6387 animTarget = getIdle();
6394 pause_sound(whooshsound);
6395 OPENAL_SetVolume(channels[whooshsound], 0);
6398 if (animTarget == jumpdownanim || isFlip()) {
6402 animTarget = getLanding();
6403 emit_sound_at(landsound, coords, 128.);
6406 addEnvSound(coords);
6411 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6412 coords.y += gravity * multiplier * 2;
6414 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
6415 coords.y = terrain.getHeight(coords.x, coords.z);
6419 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)) {
6420 velspeed = findLength(&velocity);
6422 if (velspeed < multiplier * 300 * scale) {
6425 velocity -= velocity / velspeed * multiplier * 300 * scale;
6427 if (velspeed > 5 && (isLanding() || isLandhard())) {
6428 skiddingdelay += multiplier;
6429 if (skiddelay <= 0) {
6430 FootLand(leftfoot, .5);
6431 FootLand(rightfoot, .5);
6440 velspeed = findLength(&velocity);
6442 if (velspeed > 5 && (isLanding() || isLandhard())) {
6443 skiddingdelay += multiplier;
6444 if (skiddelay <= 0) {
6445 FootLand(leftfoot, .5);
6446 FootLand(rightfoot, .5);
6454 if (skiddingdelay < 0) {
6455 skiddingdelay += multiplier;
6457 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
6459 if (!onterrain || environment == grassyenvironment) {
6460 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
6462 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
6466 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
6467 terrainnormal = victim->coords - coords;
6468 Normalise(&terrainnormal);
6469 targetyaw = -asin(0 - terrainnormal.x);
6470 targetyaw *= 360 / 6.28;
6471 if (terrainnormal.z < 0) {
6472 targetyaw = 180 - targetyaw;
6474 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
6477 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
6478 targetyaw = victim->targetyaw;
6480 if (animTarget == rabbittacklinganim) {
6481 coords = victim->coords;
6484 skeleton.oldfree = skeleton.free;
6488 midterrain.x = terrain.size * terrain.scale / 2;
6489 midterrain.z = terrain.size * terrain.scale / 2;
6490 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
6492 tempposit = coords - midterrain;
6494 Normalise(&tempposit);
6495 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
6496 coords.x = tempposit.x + midterrain.x;
6497 coords.z = tempposit.z + midterrain.z;
6502 * inverse kinematics helper function
6504 void IKHelper(Person* p, float interp)
6506 XYZ point, change, change2;
6507 float heightleft, heightright;
6509 // TODO: implement localToWorld and worldToLocal
6510 // but keep in mind it won't be the same math if player is ragdolled or something
6511 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
6512 // then comb through code for places where to use it
6514 // point = localToWorld(jointPos(leftfoot))
6515 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
6516 // adjust height of foot
6517 heightleft = terrain.getHeight(point.x, point.z) + .04;
6518 point.y = heightleft;
6519 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
6520 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
6521 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
6522 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
6523 // move ankle along with foot
6524 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
6525 // average knee pos between old and new pos
6526 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
6528 // do same as above for right leg
6529 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
6530 heightright = terrain.getHeight(point.x, point.z) + .04;
6531 point.y = heightright;
6532 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
6533 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
6534 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
6535 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
6536 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
6538 // fix up skeleton now that we've moved body parts?
6539 p->skeleton.DoConstraints(&p->coords, &p->scale);
6546 int Person::DrawSkeleton()
6548 int oldplayerdetail;
6549 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6550 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6560 glAlphaFunc(GL_GREATER, 0.0001);
6562 float terrainheight;
6564 if (!isnormal(yaw)) {
6567 if (!isnormal(tilt)) {
6570 if (!isnormal(tilt2)) {
6573 oldplayerdetail = playerdetail;
6575 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6578 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6581 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6587 if (playerdetail != oldplayerdetail) {
6589 normalsupdatedelay = 0;
6591 static float updatedelaychange;
6592 static float morphness;
6593 static float framemult;
6595 skeleton.FindForwards();
6596 if (howactive == typesittingwall) {
6597 skeleton.specialforward[1] = 0;
6598 skeleton.specialforward[1].z = 1;
6604 static int weaponattachmuscle;
6605 static int weaponrotatemuscle;
6606 static XYZ weaponpoint;
6607 static int start, endthing;
6608 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6609 if (!isSleeping() && !isSitting()) {
6610 // TODO: give these meaningful names
6611 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6612 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard() || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6614 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6616 if (creature == wolftype) {
6621 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6622 IKHelper(this, target);
6623 if (creature == wolftype) {
6624 IKHelper(this, target);
6628 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6629 IKHelper(this, 1 - target);
6630 if (creature == wolftype) {
6631 IKHelper(this, 1 - target);
6636 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())) {
6639 targetheadyaw = -targetyaw;
6640 targetheadpitch = 0;
6641 if (Animation::animations[animTarget].attack == 3) {
6642 targetheadyaw += 180;
6645 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6646 skeleton.drawmodel.vertex[i] = 0;
6647 skeleton.drawmodel.vertex[i].y = 999;
6649 for (int i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6650 skeleton.drawmodellow.vertex[i] = 0;
6651 skeleton.drawmodellow.vertex[i].y = 999;
6653 for (int i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6654 skeleton.drawmodelclothes.vertex[i] = 0;
6655 skeleton.drawmodelclothes.vertex[i].y = 999;
6657 for (unsigned int i = 0; i < skeleton.muscles.size(); i++) {
6658 // convenience renames
6659 const int p1 = skeleton.muscles[i].parent1->label;
6660 const int p2 = skeleton.muscles[i].parent2->label;
6662 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6667 if (p1 == righthand || p2 == righthand) {
6668 morphness = righthandmorphness;
6669 start = righthandmorphstart;
6670 endthing = righthandmorphend;
6672 if (p1 == lefthand || p2 == lefthand) {
6673 morphness = lefthandmorphness;
6674 start = lefthandmorphstart;
6675 endthing = lefthandmorphend;
6677 if (p1 == head || p2 == head) {
6678 morphness = headmorphness;
6679 start = headmorphstart;
6680 endthing = headmorphend;
6682 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6683 morphness = chestmorphness;
6684 start = chestmorphstart;
6685 endthing = chestmorphend;
6687 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6688 morphness = tailmorphness;
6689 start = tailmorphstart;
6690 endthing = tailmorphend;
6693 skeleton.FindRotationMuscle(i, animTarget);
6695 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6696 glMatrixMode(GL_MODELVIEW);
6699 if (!skeleton.free) {
6700 glRotatef(tilt2, 1, 0, 0);
6702 if (!skeleton.free) {
6703 glRotatef(tilt, 0, 0, 1);
6706 glTranslatef(mid.x, mid.y, mid.z);
6708 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6709 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6711 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6712 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6714 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6715 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6717 if (playerdetail || skeleton.free == 3) {
6718 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6719 XYZ& v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6720 XYZ& v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6721 glMatrixMode(GL_MODELVIEW);
6723 if (p1 == abdomen || p2 == abdomen) {
6724 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6725 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6726 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6728 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6729 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6730 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6731 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6733 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6734 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6735 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6736 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6738 if (p1 == head || p2 == head) {
6739 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6740 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6741 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6743 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6744 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6745 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6746 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6750 if (!playerdetail || skeleton.free == 3) {
6751 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6752 XYZ& v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6753 glMatrixMode(GL_MODELVIEW);
6755 if (p1 == abdomen || p2 == abdomen) {
6756 glTranslatef(v0.x * proportionbody.x,
6757 v0.y * proportionbody.y,
6758 v0.z * proportionbody.z);
6760 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6761 glTranslatef(v0.x * proportionarms.x,
6762 v0.y * proportionarms.y,
6763 v0.z * proportionarms.z);
6765 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6766 glTranslatef(v0.x * proportionlegs.x,
6767 v0.y * proportionlegs.y,
6768 v0.z * proportionlegs.z);
6770 if (p1 == head || p2 == head) {
6771 glTranslatef(v0.x * proportionhead.x,
6772 v0.y * proportionhead.y,
6773 v0.z * proportionhead.z);
6776 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6777 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6778 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6779 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6785 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6786 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6788 glMatrixMode(GL_MODELVIEW);
6791 if (!skeleton.free) {
6792 glRotatef(tilt2, 1, 0, 0);
6794 if (!skeleton.free) {
6795 glRotatef(tilt, 0, 0, 1);
6797 glTranslatef(mid.x, mid.y, mid.z);
6798 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6799 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6801 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6802 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6804 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6805 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6807 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6808 XYZ& v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6809 glMatrixMode(GL_MODELVIEW);
6811 if (p1 == abdomen || p2 == abdomen) {
6812 glTranslatef(v0.x * proportionbody.x,
6813 v0.y * proportionbody.y,
6814 v0.z * proportionbody.z);
6816 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6817 glTranslatef(v0.x * proportionarms.x,
6818 v0.y * proportionarms.y,
6819 v0.z * proportionarms.z);
6821 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6822 glTranslatef(v0.x * proportionlegs.x,
6823 v0.y * proportionlegs.y,
6824 v0.z * proportionlegs.z);
6826 if (p1 == head || p2 == head) {
6827 glTranslatef(v0.x * proportionhead.x,
6828 v0.y * proportionhead.y,
6829 v0.z * proportionhead.z);
6831 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6832 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6833 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6834 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6839 updatedelay = 1 + (float)(Random() % 100) / 1000;
6841 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6842 normalsupdatedelay = 1;
6843 if (playerdetail || skeleton.free == 3) {
6844 skeleton.drawmodel.CalculateNormals(0);
6846 if (!playerdetail || skeleton.free == 3) {
6847 skeleton.drawmodellow.CalculateNormals(0);
6849 if (skeleton.clothes) {
6850 skeleton.drawmodelclothes.CalculateNormals(0);
6853 if (playerdetail || skeleton.free == 3) {
6854 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6856 if (!playerdetail || skeleton.free == 3) {
6857 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6859 if (skeleton.clothes) {
6860 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6865 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6866 if (updatedelaychange > -realmultiplier * 30) {
6867 updatedelaychange = -realmultiplier * 30;
6869 if (updatedelaychange > -framemult * 4) {
6870 updatedelaychange = -framemult * 4;
6872 if (skeleton.free == 1) {
6873 updatedelaychange *= 6;
6876 updatedelaychange *= 8;
6878 updatedelay += updatedelaychange;
6880 glMatrixMode(GL_MODELVIEW);
6882 glTranslatef(coords.x, coords.y - .02, coords.z);
6883 if (!skeleton.free) {
6884 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6885 glRotatef(yaw, 0, 1, 0);
6889 glColor4f(.4, 1, .4, 1);
6890 glDisable(GL_LIGHTING);
6891 glDisable(GL_TEXTURE_2D);
6894 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6895 XYZ& v0 = skeleton.drawmodel.vertex[i];
6896 glVertex3f(v0.x, v0.y, v0.z);
6903 for (unsigned int i = 0; i < skeleton.drawmodel.Triangles.size(); i++) {
6904 const XYZ& v0 = skeleton.drawmodel.getTriangleVertex(i, 0);
6905 const XYZ& v1 = skeleton.drawmodel.getTriangleVertex(i, 1);
6906 const XYZ& v2 = skeleton.drawmodel.getTriangleVertex(i, 2);
6907 glVertex3f(v0.x, v0.y, v0.z);
6908 glVertex3f(v1.x, v1.y, v1.z);
6909 glVertex3f(v1.x, v1.y, v1.z);
6910 glVertex3f(v2.x, v2.y, v2.z);
6911 glVertex3f(v2.x, v2.y, v2.z);
6912 glVertex3f(v0.x, v0.y, v0.z);
6919 terrainlight = terrain.getLighting(coords.x, coords.z);
6920 distance = distsq(&viewer, &coords);
6921 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6926 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6927 if (terrainheight < 1) {
6930 if (terrainheight > 1.7) {
6931 terrainheight = 1.7;
6934 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6935 glDisable(GL_BLEND);
6936 glAlphaFunc(GL_GREATER, 0.0001);
6937 glEnable(GL_TEXTURE_2D);
6939 glDisable(GL_TEXTURE_2D);
6940 glColor4f(.7, .35, 0, .5);
6942 glEnable(GL_LIGHTING);
6945 if (Tutorial::active && id != 0) {
6946 glColor4f(.7, .7, .7, 0.6);
6948 glEnable(GL_LIGHTING);
6950 if (canattack && cananger) {
6951 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6952 glDisable(GL_TEXTURE_2D);
6953 glColor4f(1, 0, 0, 0.8);
6956 glMatrixMode(GL_TEXTURE);
6958 glTranslatef(0, -smoketex, 0);
6959 glTranslatef(-smoketex, 0, 0);
6963 if (Tutorial::active && (id != 0)) {
6964 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6966 skeleton.drawmodel.draw();
6970 if (!playerdetail) {
6971 if (Tutorial::active && (id != 0)) {
6972 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6974 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6978 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed)) {
6979 if (Tutorial::active && id != 0) {
6981 glMatrixMode(GL_MODELVIEW);
6982 glEnable(GL_TEXTURE_2D);
6983 glColor4f(.7, .7, .7, 0.6);
6985 glEnable(GL_LIGHTING);
6987 if (canattack && cananger) {
6988 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6989 glDisable(GL_TEXTURE_2D);
6990 glColor4f(1, 0, 0, 0.8);
6993 glMatrixMode(GL_TEXTURE);
6995 glTranslatef(0, -smoketex * .6, 0);
6996 glTranslatef(smoketex * .6, 0, 0);
6999 if (Tutorial::active && (id != 0)) {
7000 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
7002 skeleton.drawmodel.draw();
7006 if (!playerdetail) {
7007 if (Tutorial::active && (id != 0)) {
7008 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
7010 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
7016 if (Tutorial::active && id != 0) {
7018 glMatrixMode(GL_MODELVIEW);
7019 glEnable(GL_TEXTURE_2D);
7021 if (skeleton.clothes) {
7025 skeleton.drawmodelclothes.draw();
7028 skeleton.drawmodelclothes.drawimmediate();
7035 if (num_weapons > 0) {
7036 for (k = 0; k < num_weapons; k++) {
7037 int i = weaponids[k];
7038 if (weaponactive == k) {
7039 if (weapons[i].getType() != staff) {
7040 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7041 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
7042 weaponattachmuscle = j;
7045 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7046 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) {
7047 weaponrotatemuscle = j;
7050 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
7051 if (creature == wolftype) {
7052 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
7055 if (weapons[i].getType() == staff) {
7056 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7057 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
7058 weaponattachmuscle = j;
7061 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7062 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) {
7063 weaponrotatemuscle = j;
7066 //weaponpoint=jointPos(rightwrist);
7067 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
7068 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
7069 XYZ tempnormthing, vec1, vec2;
7070 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
7071 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
7072 CrossProduct(&vec1, &vec2, &tempnormthing);
7073 Normalise(&tempnormthing);
7074 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim) {
7075 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
7079 if (weaponactive != k && weaponstuck != k) {
7080 if (weapons[i].getType() == knife) {
7081 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
7083 if (weapons[i].getType() == sword) {
7084 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
7086 if (weapons[i].getType() == staff) {
7087 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
7089 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7090 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) {
7091 weaponrotatemuscle = j;
7095 if (weaponstuck == k) {
7096 if (weaponstuckwhere == 0) {
7097 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
7099 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
7101 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7102 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) {
7103 weaponrotatemuscle = j;
7107 if (skeleton.free) {
7108 weapons[i].position = weaponpoint * scale + coords;
7109 weapons[i].bigrotation = 0;
7110 weapons[i].bigtilt = 0;
7111 weapons[i].bigtilt2 = 0;
7113 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;
7114 weapons[i].bigrotation = yaw;
7115 weapons[i].bigtilt = tilt;
7116 weapons[i].bigtilt2 = tilt2;
7118 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
7119 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
7120 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
7121 if (weaponactive == k) {
7122 if (weapons[i].getType() == knife) {
7123 weapons[i].smallrotation = 180;
7124 weapons[i].smallrotation2 = 0;
7125 if (isCrouch() || wasCrouch()) {
7126 weapons[i].smallrotation2 = 20;
7128 if (animTarget == hurtidleanim) {
7129 weapons[i].smallrotation2 = 50;
7131 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
7132 XYZ temppoint1, temppoint2;
7135 temppoint1 = jointPos(righthand);
7136 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7137 distance = findDistance(&temppoint1, &temppoint2);
7138 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7139 weapons[i].rotation2 *= 360 / 6.28;
7142 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7143 weapons[i].rotation1 *= 360 / 6.28;
7144 weapons[i].rotation3 = 0;
7145 weapons[i].smallrotation = -90;
7146 weapons[i].smallrotation2 = 0;
7147 if (temppoint1.x > temppoint2.x) {
7148 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7151 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
7152 XYZ temppoint1, temppoint2;
7155 temppoint1 = jointPos(righthand);
7156 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7157 distance = findDistance(&temppoint1, &temppoint2);
7158 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7159 weapons[i].rotation2 *= 360 / 6.28;
7162 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7163 weapons[i].rotation1 *= 360 / 6.28;
7164 weapons[i].rotation3 = 0;
7165 weapons[i].smallrotation = 90;
7166 weapons[i].smallrotation2 = 0;
7167 if (temppoint1.x > temppoint2.x) {
7168 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7171 if (animTarget == knifethrowanim) {
7172 weapons[i].smallrotation = 90;
7173 //weapons[i].smallrotation2=-90;
7174 weapons[i].smallrotation2 = 0;
7175 weapons[i].rotation1 = 0;
7176 weapons[i].rotation2 = 0;
7177 weapons[i].rotation3 = 0;
7179 if (animTarget == knifesneakattackanim && frameTarget < 5) {
7180 weapons[i].smallrotation = -90;
7181 weapons[i].rotation1 = 0;
7182 weapons[i].rotation2 = 0;
7183 weapons[i].rotation3 = 0;
7186 if (weapons[i].getType() == sword) {
7187 weapons[i].smallrotation = 0;
7188 weapons[i].smallrotation2 = 0;
7189 if (animTarget == knifethrowanim) {
7190 weapons[i].smallrotation = -90;
7191 weapons[i].smallrotation2 = 0;
7192 weapons[i].rotation1 = 0;
7193 weapons[i].rotation2 = 0;
7194 weapons[i].rotation3 = 0;
7196 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)) {
7197 XYZ temppoint1, temppoint2;
7200 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
7201 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7202 distance = findDistance(&temppoint1, &temppoint2);
7203 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7204 weapons[i].rotation2 *= 360 / 6.28;
7207 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7208 weapons[i].rotation1 *= 360 / 6.28;
7209 weapons[i].rotation3 = 0;
7210 weapons[i].smallrotation = 90;
7211 weapons[i].smallrotation2 = 0;
7212 if (temppoint1.x > temppoint2.x) {
7213 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7217 if (weapons[i].getType() == staff) {
7218 weapons[i].smallrotation = 100;
7219 weapons[i].smallrotation2 = 0;
7220 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
7221 XYZ temppoint1, temppoint2;
7224 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
7225 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7226 distance = findDistance(&temppoint1, &temppoint2);
7227 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7228 weapons[i].rotation2 *= 360 / 6.28;
7231 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7232 weapons[i].rotation1 *= 360 / 6.28;
7233 weapons[i].rotation3 = 0;
7234 weapons[i].smallrotation = 90;
7235 weapons[i].smallrotation2 = 0;
7236 if (temppoint1.x > temppoint2.x) {
7237 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7242 if (weaponactive != k && weaponstuck != k) {
7243 if (weapons[i].getType() == knife) {
7244 weapons[i].smallrotation = -70;
7245 weapons[i].smallrotation2 = 10;
7247 if (weapons[i].getType() == sword) {
7248 weapons[i].smallrotation = -100;
7249 weapons[i].smallrotation2 = -8;
7251 if (weapons[i].getType() == staff) {
7252 weapons[i].smallrotation = -100;
7253 weapons[i].smallrotation2 = -8;
7256 if (weaponstuck == k) {
7257 if (weaponstuckwhere == 0) {
7258 weapons[i].smallrotation = 180;
7260 weapons[i].smallrotation = 0;
7262 weapons[i].smallrotation2 = 10;
7269 if (skeleton.free) {
7272 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump()) {
7275 if (animCurrent != animTarget) {
7278 if (skeleton.free == 2) {
7287 int Person::SphereCheck(XYZ* p1, float radius, XYZ* p, XYZ* move, float* rotate, Model* model)
7289 static float distance;
7290 static float olddistance;
7291 static int intersecting;
7292 static int firstintersecting;
7295 static XYZ start, end;
7296 static float slopethreshold = -.4;
7298 firstintersecting = -1;
7302 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius) {
7306 *p1 = DoRotation(*p1, 0, -*rotate, 0);
7308 for (int i = 0; i < 4; i++) {
7309 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7310 if (model->Triangles[j].facenormal.y <= slopethreshold) {
7312 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)));
7313 if (distance < radius) {
7314 point = *p1 - model->Triangles[j].facenormal * distance;
7315 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]])) {
7318 if (!intersecting) {
7319 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7320 &model->vertex[model->Triangles[j].vertex[1]],
7323 if (!intersecting) {
7324 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
7325 &model->vertex[model->Triangles[j].vertex[2]],
7328 if (!intersecting) {
7329 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7330 &model->vertex[model->Triangles[j].vertex[2]],
7334 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7338 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)) {
7339 p1->y = point.y + radius;
7340 if ((animTarget == jumpdownanim || isFlip())) {
7341 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4)) {
7345 if (animTarget == jumpupanim) {
7347 animTarget = getIdle();
7354 pause_sound(whooshsound);
7355 OPENAL_SetVolume(channels[whooshsound], 0);
7358 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
7362 animTarget = getLanding();
7363 emit_sound_at(landsound, coords, 128.);
7366 addEnvSound(coords);
7373 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7374 olddistance = distance;
7375 firstintersecting = j;
7380 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7381 if (model->Triangles[j].facenormal.y > slopethreshold) {
7384 start.y -= radius / 4;
7385 XYZ& v0 = model->vertex[model->Triangles[j].vertex[0]];
7386 XYZ& v1 = model->vertex[model->Triangles[j].vertex[1]];
7387 XYZ& v2 = model->vertex[model->Triangles[j].vertex[2]];
7388 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)));
7389 if (distance < radius * .5) {
7390 point = start - model->Triangles[j].facenormal * distance;
7391 if (PointInTriangle(&point, model->Triangles[j].facenormal, &v0, &v1, &v2)) {
7394 if (!intersecting) {
7395 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
7397 if (!intersecting) {
7398 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7400 if (!intersecting) {
7401 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7404 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7405 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
7407 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;
7408 if (findLengthfast(&start) < findLengthfast(&velocity)) {
7412 *p1 += model->Triangles[j].facenormal * (distance - radius * .5);
7415 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7416 olddistance = distance;
7417 firstintersecting = j;
7424 *p = DoRotation(*p, 0, *rotate, 0);
7428 *p1 = DoRotation(*p1, 0, *rotate, 0);
7431 return firstintersecting;
7434 int findPathDist(int start, int end)
7439 unsigned int smallestcount = 1000;
7440 for (char i = 0; i < 50; i++) {
7441 unsigned int count = 0;
7446 while (last != end && count < 30) {
7448 for (int j = 0; j < Game::numpathpoints; j++) {
7449 if (j != last && j != last2 && j != last3 && j != last4) {
7451 if (Game::numpathpointconnect[j]) {
7452 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7453 if (Game::pathpointconnect[j][k] == last) {
7459 if (Game::numpathpointconnect[last]) {
7460 for (int k = 0; k < Game::numpathpointconnect[last]; k++) {
7461 if (Game::pathpointconnect[last][k] == j) {
7468 if (closest == -1 || Random() % 2 == 0) {
7480 if (count < smallestcount) {
7481 smallestcount = count;
7484 return smallestcount;
7487 void Person::takeWeapon(int weaponId)
7490 weapons[weaponId].owner = id;
7491 if (num_weapons > 0) {
7492 weaponids[num_weapons] = weaponids[0];
7495 weaponids[0] = weaponId;
7498 void Person::addClothes()
7500 if (numclothes > 0) {
7501 for (int i = 0; i < numclothes; i++) {
7508 bool Person::addClothes(const int& clothesId)
7511 const std::string fileName = clothes[clothesId];
7513 GLubyte* array = &skeleton.skinText[0];
7517 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
7522 float tintr = clothestintr[clothesId];
7523 float tintg = clothestintg[clothesId];
7524 float tintb = clothestintb[clothesId];
7546 int bytesPerPixel = texture.bpp / 8;
7550 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
7551 if (bytesPerPixel == 3) {
7553 } else if ((i + 1) % 4 == 0) {
7554 alphanum = texture.data[i];
7556 if ((i + 1) % 4 || bytesPerPixel == 3) {
7558 texture.data[i] *= tintr;
7561 texture.data[i] *= tintg;
7564 texture.data[i] *= tintb;
7566 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
7578 if (aitype != playercontrolled && !Dialog::inDialog()) {
7580 //disable movement in editor
7581 if (Game::editorenabled) {
7586 if (distsqflat(&Person::players[0]->coords, &coords) < 30 &&
7587 Person::players[0]->coords.y > coords.y + 2 &&
7588 !Person::players[0]->onterrain) {
7593 if (aitype == pathfindtype) {
7594 if (finalpathfindpoint == -1) {
7595 float closestdistance;
7596 float tempdist = 0.0f;
7600 closestdistance = -1;
7601 for (int j = 0; j < Game::numpathpoints; j++) {
7602 if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) {
7603 closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]);
7605 finaltarget = Game::pathpoint[j];
7608 finalpathfindpoint = closest;
7609 for (int j = 0; j < Game::numpathpoints; j++) {
7610 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7611 DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7612 if (sq(tempdist) < closestdistance) {
7613 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7614 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7615 closestdistance = sq(tempdist);
7617 finaltarget = colpoint;
7622 finalpathfindpoint = closest;
7624 if (targetpathfindpoint == -1) {
7625 float closestdistance;
7626 float tempdist = 0.0f;
7630 closestdistance = -1;
7631 if (lastpathfindpoint == -1) {
7632 for (int j = 0; j < Game::numpathpoints; j++) {
7633 if (j != lastpathfindpoint) {
7634 if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) {
7635 closestdistance = distsq(&coords, &Game::pathpoint[j]);
7640 targetpathfindpoint = closest;
7641 for (int j = 0; j < Game::numpathpoints; j++) {
7642 if (j != lastpathfindpoint) {
7643 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7644 DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7645 if (sq(tempdist) < closestdistance) {
7646 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7647 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7648 closestdistance = sq(tempdist);
7655 targetpathfindpoint = closest;
7657 for (int j = 0; j < Game::numpathpoints; j++) {
7658 if (j != lastpathfindpoint &&
7659 j != lastpathfindpoint2 &&
7660 j != lastpathfindpoint3 &&
7661 j != lastpathfindpoint4) {
7663 if (Game::numpathpointconnect[j]) {
7664 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7665 if (Game::pathpointconnect[j][k] == lastpathfindpoint) {
7671 if (Game::numpathpointconnect[lastpathfindpoint]) {
7672 for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++) {
7673 if (Game::pathpointconnect[lastpathfindpoint][k] == j) {
7680 tempdist = findPathDist(j, finalpathfindpoint);
7681 if (closest == -1 || tempdist < closestdistance) {
7682 closestdistance = tempdist;
7688 targetpathfindpoint = closest;
7691 losupdatedelay -= multiplier;
7693 targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]);
7694 lookyaw = targetyaw;
7696 //reached target point
7697 if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) {
7698 lastpathfindpoint4 = lastpathfindpoint3;
7699 lastpathfindpoint3 = lastpathfindpoint2;
7700 lastpathfindpoint2 = lastpathfindpoint;
7701 lastpathfindpoint = targetpathfindpoint;
7702 if (lastpathfindpoint2 == -1) {
7703 lastpathfindpoint2 = lastpathfindpoint;
7705 if (lastpathfindpoint3 == -1) {
7706 lastpathfindpoint3 = lastpathfindpoint2;
7708 if (lastpathfindpoint4 == -1) {
7709 lastpathfindpoint4 = lastpathfindpoint3;
7711 targetpathfindpoint = -1;
7713 if (distsqflat(&coords, &finalfinaltarget) <
7714 distsqflat(&coords, &finaltarget) ||
7715 distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) ||
7716 lastpathfindpoint == finalpathfindpoint) {
7717 aitype = passivetype;
7728 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7729 targetyaw += 90 * (whichdirection * 2 - 1);
7732 if (collided < 1 || animTarget != jumpupanim) {
7735 if ((collided > .8 && jumppower >= 5)) {
7739 if ((!Tutorial::active || cananger) &&
7741 !Person::players[0]->dead &&
7742 distsq(&coords, &Person::players[0]->coords) < 400 &&
7744 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7745 Animation::animations[Person::players[0]->animTarget].height != lowheight &&
7746 !Game::editorenabled &&
7747 (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain)) {
7748 aitype = attacktypecutoff;
7750 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7751 Animation::animations[Person::players[0]->animTarget].height == highheight &&
7752 !Game::editorenabled) {
7753 aitype = attacktypecutoff;
7756 if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7757 losupdatedelay = .2;
7758 for (unsigned j = 0; j < Person::players.size(); j++) {
7759 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7760 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7761 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7762 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7763 if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain) {
7764 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) ||
7765 (Person::players[j]->animTarget == hanganim &&
7766 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7767 aitype = searchtype;
7769 lastseen = Person::players[j]->coords;
7780 if (aitype == attacktypecutoff && Game::musictype != 2) {
7781 if (creature != wolftype) {
7788 if (aitype != passivetype && Game::leveltime > .5) {
7789 howactive = typeactive;
7792 if (aitype == passivetype) {
7793 aiupdatedelay -= multiplier;
7794 losupdatedelay -= multiplier;
7795 lastseentime += multiplier;
7796 pausetime -= multiplier;
7797 if (lastseentime > 1) {
7801 if (aiupdatedelay < 0) {
7802 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7803 targetyaw = roughDirectionTo(coords, waypoints[waypoint]);
7804 lookyaw = targetyaw;
7805 aiupdatedelay = .05;
7807 if (distsqflat(&coords, &waypoints[waypoint]) < 1) {
7808 if (waypointtype[waypoint] == wppause) {
7812 if (waypoint > numwaypoints - 1) {
7818 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7830 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7831 if (!avoidsomething) {
7832 targetyaw += 90 * (whichdirection * 2 - 1);
7834 XYZ leftpos, rightpos;
7835 float leftdist, rightdist;
7836 leftpos = coords + DoRotation(facing, 0, 90, 0);
7837 rightpos = coords - DoRotation(facing, 0, 90, 0);
7838 leftdist = distsq(&leftpos, &avoidwhere);
7839 rightdist = distsq(&rightpos, &avoidwhere);
7840 if (leftdist < rightdist) {
7848 if (collided < 1 || animTarget != jumpupanim) {
7851 if ((collided > .8 && jumppower >= 5)) {
7856 if (!Game::editorenabled) {
7857 if (howactive <= typesleeping) {
7858 if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile) {
7859 for (int j = 0; j < numenvsounds; j++) {
7860 float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
7861 if (vol > 0 && distsq(&coords, &envsound[j]) < 2 * (vol + vol * (creature == rabbittype) * 3)) {
7862 aitype = attacktypecutoff;
7868 if (aitype != passivetype) {
7869 if (howactive == typesleeping) {
7870 setTargetAnimation(getupfromfrontanim);
7872 howactive = typeactive;
7876 if (howactive < typesleeping &&
7877 ((!Tutorial::active || cananger) && hostile) &&
7878 !Person::players[0]->dead &&
7879 distsq(&coords, &Person::players[0]->coords) < 400 &&
7881 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7882 Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled) {
7883 aitype = attacktypecutoff;
7885 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7886 Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled) {
7887 aitype = attacktypecutoff;
7891 if (creature == wolftype) {
7893 for (unsigned j = 0; j < Person::players.size(); j++) {
7894 if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
7895 float smelldistance = 50;
7896 if (j == 0 && Person::players[j]->num_weapons > 0) {
7897 if (weapons[Person::players[j]->weaponids[0]].bloody) {
7898 smelldistance = 100;
7900 if (Person::players[j]->num_weapons == 2) {
7901 if (weapons[Person::players[j]->weaponids[1]].bloody) {
7902 smelldistance = 100;
7907 smelldistance = 100;
7909 windsmell = windvector;
7910 Normalise(&windsmell);
7911 windsmell = windsmell * 2 + Person::players[j]->coords;
7912 if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled) {
7913 aitype = attacktypecutoff;
7919 if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7920 losupdatedelay = .2;
7921 for (unsigned j = 0; j < Person::players.size(); j++) {
7922 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7923 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7924 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7925 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7926 if ((-1 == Object::checkcollide(
7927 DoRotation(jointPos(head), 0, yaw, 0) *
7930 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0) *
7931 Person::players[j]->scale +
7932 Person::players[j]->coords) &&
7933 !Person::players[j]->isWallJump()) ||
7934 (Person::players[j]->animTarget == hanganim &&
7935 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7937 if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight) {
7946 if (lastseentime <= 0) {
7947 aitype = searchtype;
7949 lastseen = Person::players[j]->coords;
7957 if (aitype == attacktypecutoff && Game::musictype != 2) {
7958 if (creature != wolftype) {
7962 if (creature == wolftype) {
7972 if (aitype == searchtype) {
7973 aiupdatedelay -= multiplier;
7974 losupdatedelay -= multiplier;
7976 lastseentime -= multiplier;
7978 lastchecktime -= multiplier;
7980 if (isRun() && !onground) {
7981 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7982 XYZ test2 = coords + facing;
7984 XYZ test = coords + facing;
7986 j = Object::checkcollide(test2, test, laststanding);
7988 j = Object::checkcollide(test2, test);
7992 setTargetAnimation(getStop());
7995 //aitype=passivetype;
7996 aitype = pathfindtype;
7997 finalfinaltarget = waypoints[waypoint];
7998 finalpathfindpoint = -1;
7999 targetpathfindpoint = -1;
8000 lastpathfindpoint = -1;
8001 lastpathfindpoint2 = -1;
8002 lastpathfindpoint3 = -1;
8003 lastpathfindpoint4 = -1;
8009 //check out last seen location
8010 if (aiupdatedelay < 0) {
8011 targetyaw = roughDirectionTo(coords, lastseen);
8012 lookyaw = targetyaw;
8013 aiupdatedelay = .05;
8016 if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) {
8019 lastseen.x += (float(Random() % 100) - 50) / 25;
8020 lastseen.z += (float(Random() % 100) - 50) / 25;
8031 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8032 if (!avoidsomething) {
8033 targetyaw += 90 * (whichdirection * 2 - 1);
8035 XYZ leftpos, rightpos;
8036 float leftdist, rightdist;
8037 leftpos = coords + DoRotation(facing, 0, 90, 0);
8038 rightpos = coords - DoRotation(facing, 0, 90, 0);
8039 leftdist = distsq(&leftpos, &avoidwhere);
8040 rightdist = distsq(&rightpos, &avoidwhere);
8041 if (leftdist < rightdist) {
8049 if (collided < 1 || animTarget != jumpupanim) {
8052 if ((collided > .8 && jumppower >= 5)) {
8056 if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile)) {
8057 for (int k = 0; k < numenvsounds; k++) {
8058 if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) {
8059 aitype = attacktypecutoff;
8064 if (!Person::players[0]->dead &&
8065 losupdatedelay < 0 &&
8066 !Game::editorenabled &&
8068 ((!Tutorial::active || cananger) && hostile)) {
8069 losupdatedelay = .2;
8070 if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) {
8071 aitype = attacktypecutoff;
8074 if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight) {
8075 //TODO: factor out canSeePlayer()
8076 if (distsq(&coords, &Person::players[0]->coords) < 400) {
8077 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
8078 if ((Object::checkcollide(
8079 DoRotation(jointPos(head), 0, yaw, 0) *
8082 DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0) *
8083 Person::players[0]->scale +
8084 Person::players[0]->coords) == -1) ||
8085 (Person::players[0]->animTarget == hanganim && normaldotproduct(Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) {
8086 /* //TODO: changed j to 0 on a whim, make sure this is correct
8087 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
8088 Person::players[j]->facing,coords-Person::players[j]->coords)<0)
8090 aitype = attacktypecutoff;
8098 if (lastseentime < 0) {
8099 //aitype=passivetype;
8101 aitype = pathfindtype;
8102 finalfinaltarget = waypoints[waypoint];
8103 finalpathfindpoint = -1;
8104 targetpathfindpoint = -1;
8105 lastpathfindpoint = -1;
8106 lastpathfindpoint2 = -1;
8107 lastpathfindpoint3 = -1;
8108 lastpathfindpoint4 = -1;
8112 if (aitype != gethelptype) {
8116 //get help from buddies
8117 if (aitype == gethelptype) {
8118 runninghowlong += multiplier;
8119 aiupdatedelay -= multiplier;
8121 if (aiupdatedelay < 0 || ally == 0) {
8125 //TODO: factor out closest search somehow
8128 float closestdist = -1;
8129 for (unsigned k = 0; k < Person::players.size(); k++) {
8130 if ((k != id) && (k != 0) && !Person::players[k]->dead &&
8131 (Person::players[k]->howactive < typedead1) &&
8132 !Person::players[k]->skeleton.free &&
8133 (Person::players[k]->aitype == passivetype)) {
8134 float distance = distsq(&coords, &Person::players[k]->coords);
8135 if (closestdist == -1 || distance < closestdist) {
8136 closestdist = distance;
8141 if (closest != -1) {
8146 lastseen = Person::players[0]->coords;
8152 XYZ facing = coords;
8153 XYZ flatfacing = Person::players[ally]->coords;
8154 facing.y += jointPos(head).y * scale;
8155 flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale;
8156 if (-1 != Object::checkcollide(facing, flatfacing)) {
8160 //no available ally, run back to player
8162 Person::players[ally]->skeleton.free ||
8163 Person::players[ally]->aitype != passivetype ||
8164 lastseentime <= 0) {
8165 aitype = searchtype;
8171 targetyaw = roughDirectionTo(coords, Person::players[ally]->coords);
8172 lookyaw = targetyaw;
8173 aiupdatedelay = .05;
8176 if (distsqflat(&coords, &Person::players[ally]->coords) < 3) {
8177 aitype = searchtype;
8179 Person::players[ally]->aitype = searchtype;
8180 if (Person::players[ally]->lastseentime < lastseentime) {
8181 Person::players[ally]->lastseen = lastseen;
8182 Person::players[ally]->lastseentime = lastseentime;
8183 Person::players[ally]->lastchecktime = lastchecktime;
8187 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8188 if (!avoidsomething) {
8189 targetyaw += 90 * (whichdirection * 2 - 1);
8191 XYZ leftpos, rightpos;
8192 float leftdist, rightdist;
8193 leftpos = coords + DoRotation(facing, 0, 90, 0);
8194 rightpos = coords - DoRotation(facing, 0, 90, 0);
8195 leftdist = distsq(&leftpos, &avoidwhere);
8196 rightdist = distsq(&rightpos, &avoidwhere);
8197 if (leftdist < rightdist) {
8212 if (collided < 1 || animTarget != jumpupanim) {
8215 if (collided > .8 && jumppower >= 5) {
8220 //retreiving a weapon on the ground
8221 if (aitype == getweapontype) {
8222 aiupdatedelay -= multiplier;
8223 lastchecktime -= multiplier;
8225 if (aiupdatedelay < 0) {
8231 float closestdist = -1;
8232 for (unsigned k = 0; k < weapons.size(); k++) {
8233 if (weapons[k].owner == -1) {
8234 float distance = distsq(&coords, &weapons[k].position);
8235 if (closestdist == -1 || distance < closestdist) {
8236 closestdist = distance;
8241 if (closest != -1) {
8250 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile)) {
8251 if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) {
8252 aitype = attacktypecutoff;
8256 if (!Person::players[0]->dead) {
8258 if (weapons[ally].owner != -1 ||
8259 distsq(&coords, &weapons[ally].position) > 16) {
8260 aitype = attacktypecutoff;
8263 //TODO: factor these out as moveToward()
8264 targetyaw = roughDirectionTo(coords, weapons[ally].position);
8265 lookyaw = targetyaw;
8266 aiupdatedelay = .05;
8269 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8270 if (!avoidsomething) {
8271 targetyaw += 90 * (whichdirection * 2 - 1);
8273 XYZ leftpos, rightpos;
8274 float leftdist, rightdist;
8275 leftpos = coords + DoRotation(facing, 0, 90, 0);
8276 rightpos = coords - DoRotation(facing, 0, 90, 0);
8277 leftdist = distsq(&leftpos, &avoidwhere);
8278 rightdist = distsq(&rightpos, &avoidwhere);
8279 if (leftdist < rightdist) {
8295 if (animTarget != crouchremoveknifeanim &&
8296 animTarget != removeknifeanim) {
8297 throwtogglekeydown = 0;
8301 if (collided < 1 || animTarget != jumpupanim) {
8304 if ((collided > .8 && jumppower >= 5)) {
8309 if (aitype == attacktypecutoff) {
8310 aiupdatedelay -= multiplier;
8311 //dodge or reverse rabbit kicks, knife throws, flips
8312 if (damage < damagetolerance * 2 / 3) {
8313 if ((Person::players[0]->animTarget == rabbitkickanim ||
8314 Person::players[0]->animTarget == knifethrowanim ||
8315 (Person::players[0]->isFlip() &&
8316 normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) &&
8317 !Person::players[0]->skeleton.free &&
8318 (aiupdatedelay < .1)) {
8323 if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
8324 if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
8325 if (isIdle() || isCrouch() || isRun() || isFlip()) {
8326 if (abs(Random() % 2) == 0) {
8327 setTargetAnimation(backhandspringanim);
8329 setTargetAnimation(rollanim);
8331 targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
8334 if (animTarget == jumpupanim || animTarget == jumpdownanim) {
8335 setTargetAnimation(flipanim);
8340 aiupdatedelay = .02;
8343 //get confused by flips
8344 if (Person::players[0]->isFlip() &&
8345 !Person::players[0]->skeleton.free &&
8346 Person::players[0]->animTarget != walljumprightkickanim &&
8347 Person::players[0]->animTarget != walljumpleftkickanim) {
8348 if (distsq(&Person::players[0]->coords, &coords) < 25) {
8349 if ((1 - damage / damagetolerance) > .5) {
8354 //go for weapon on the ground
8355 if (wentforweapon < 3) {
8356 for (unsigned k = 0; k < weapons.size(); k++) {
8357 if (creature != wolftype) {
8358 if (num_weapons == 0 &&
8359 weapons[k].owner == -1 &&
8360 weapons[k].velocity.x == 0 &&
8361 weapons[k].velocity.z == 0 &&
8362 weapons[k].velocity.y == 0) {
8363 if (distsq(&coords, &weapons[k].position) < 16) {
8366 aitype = getweapontype;
8373 //dodge/reverse walljump kicks
8374 if (damage < damagetolerance / 2) {
8375 if (Animation::animations[animTarget].height != highheight) {
8376 if (damage < damagetolerance * .5 &&
8377 ((Person::players[0]->animTarget == walljumprightkickanim ||
8378 Person::players[0]->animTarget == walljumpleftkickanim) &&
8379 ((aiupdatedelay < .15 &&
8381 (aiupdatedelay < .08 &&
8382 difficulty != 2)))) {
8387 //walked off a ledge (?)
8388 if (isRun() && !onground) {
8389 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
8390 XYZ test2 = coords + facing;
8392 XYZ test = coords + facing;
8394 j = Object::checkcollide(test2, test, laststanding);
8396 j = Object::checkcollide(test2, test);
8400 setTargetAnimation(getStop());
8403 aitype = pathfindtype;
8404 finalfinaltarget = waypoints[waypoint];
8405 finalpathfindpoint = -1;
8406 targetpathfindpoint = -1;
8407 lastpathfindpoint = -1;
8408 lastpathfindpoint2 = -1;
8409 lastpathfindpoint3 = -1;
8410 lastpathfindpoint4 = -1;
8416 //lose sight of player in the air (?)
8417 if (Person::players[0]->coords.y > coords.y + 5 &&
8418 Animation::animations[Person::players[0]->animTarget].height != highheight &&
8419 !Person::players[0]->onterrain) {
8420 aitype = pathfindtype;
8421 finalfinaltarget = waypoints[waypoint];
8422 finalpathfindpoint = -1;
8423 targetpathfindpoint = -1;
8424 lastpathfindpoint = -1;
8425 lastpathfindpoint2 = -1;
8426 lastpathfindpoint3 = -1;
8427 lastpathfindpoint4 = -1;
8429 //it's time to think (?)
8430 if (aiupdatedelay < 0 &&
8431 !Animation::animations[animTarget].attack &&
8432 animTarget != staggerbackhighanim &&
8433 animTarget != staggerbackhardanim &&
8434 animTarget != backhandspringanim &&
8435 animTarget != dodgebackanim) {
8437 if (weaponactive == -1 && num_weapons > 0) {
8438 drawkeydown = Random() % 2;
8442 rabbitkickenabled = Random() % 2;
8444 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
8445 XYZ targetpoint = Person::players[0]->coords;
8446 float vellength = findLength(&velocity);
8447 if (vellength != 0 &&
8448 distsq(&Person::players[0]->coords, &coords) < distsq(&rotatetarget, &coords)) {
8449 targetpoint += Person::players[0]->velocity *
8450 findDistance(&Person::players[0]->coords, &coords) / vellength;
8452 targetyaw = roughDirectionTo(coords, targetpoint);
8453 lookyaw = targetyaw;
8454 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
8456 if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1)) {
8458 } else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
8459 distsq(&coords, &Person::players[0]->coords) < 9) &&
8460 Person::players[0]->weaponactive != -1) {
8462 } else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0)) {
8467 //chill out around the corpse
8468 if (Person::players[0]->dead) {
8470 if (Random() % 10 == 0) {
8473 if (Random() % 100 == 0) {
8474 aitype = pathfindtype;
8475 finalfinaltarget = waypoints[waypoint];
8476 finalpathfindpoint = -1;
8477 targetpathfindpoint = -1;
8478 lastpathfindpoint = -1;
8479 lastpathfindpoint2 = -1;
8480 lastpathfindpoint3 = -1;
8481 lastpathfindpoint4 = -1;
8490 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8491 targetyaw += 90 * (whichdirection * 2 - 1);
8494 if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype) {
8499 if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7) {
8504 if (aitype != playercontrolled &&
8509 for (unsigned j = 0; j < Person::players.size(); j++) {
8510 if (j != id && !Person::players[j]->skeleton.free &&
8511 Person::players[j]->hasvictim &&
8512 (Tutorial::active && reversaltrain ||
8513 Random() % 2 == 0 && difficulty == 2 ||
8514 Random() % 4 == 0 && difficulty == 1 ||
8515 Random() % 8 == 0 && difficulty == 0 ||
8516 Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
8517 Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
8518 (Random() % 2 == 0 || difficulty == 2) ||
8519 (isIdle() || isRun()) &&
8520 Person::players[j]->weaponactive != -1 ||
8521 Person::players[j]->animTarget == swordslashanim &&
8522 weaponactive != -1 ||
8523 Person::players[j]->animTarget == staffhitanim ||
8524 Person::players[j]->animTarget == staffspinhitanim)) {
8525 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
8526 Person::players[j]->victim == Person::players[id] &&
8527 (Person::players[j]->animTarget == sweepanim ||
8528 Person::players[j]->animTarget == spinkickanim ||
8529 Person::players[j]->animTarget == staffhitanim ||
8530 Person::players[j]->animTarget == staffspinhitanim ||
8531 Person::players[j]->animTarget == winduppunchanim ||
8532 Person::players[j]->animTarget == upunchanim ||
8533 Person::players[j]->animTarget == wolfslapanim ||
8534 Person::players[j]->animTarget == knifeslashstartanim ||
8535 Person::players[j]->animTarget == swordslashanim &&
8536 (distsq(&Person::players[j]->coords, &coords) < 2 ||
8537 weaponactive != -1))) {
8547 Person::players[target]->Reverse();
8554 if (collided > .8 && jumppower >= 5 ||
8555 distsq(&coords, &Person::players[0]->coords) > 400 &&
8557 creature == rabbittype) {
8560 //TODO: why are we controlling the human?
8561 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
8562 Person::players[0]->jumpkeydown = 0;
8564 if (Person::players[0]->animTarget == jumpdownanim &&
8565 distsq(&Person::players[0]->coords, &coords) < 40) {
8572 if (Tutorial::active) {
8578 XYZ facing = coords;
8579 XYZ flatfacing = Person::players[0]->coords;
8580 facing.y += jointPos(head).y * scale;
8581 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
8582 if (occluded >= 2) {
8583 if (-1 != Object::checkcollide(facing, flatfacing)) {
8587 if (lastseentime <= 0 &&
8588 (creature != wolftype ||
8589 weaponstuck == -1)) {
8590 aitype = searchtype;
8592 lastseen = Person::players[0]->coords;
8601 if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
8602 (aitype == attacktypecutoff ||
8603 aitype == searchtype)) {
8604 if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
8605 XYZ test = Person::players[0]->coords;
8607 if (-1 == Object::checkcollide(Person::players[0]->coords, test)) {
8613 if (aitype == passivetype && !(numwaypoints > 1) ||
8615 pause && damage > superpermanentdamage) {
8634 XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0);
8635 facing = flatfacing;
8637 if (aitype == attacktypecutoff) {
8638 targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
8639 targetheadpitch = pitchTo(coords, Person::players[0]->coords);
8640 } else if (howactive >= typesleeping) {
8641 targetheadyaw = targetyaw;
8642 targetheadpitch = 0;
8644 if (interestdelay <= 0) {
8645 interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
8646 headtarget = coords;
8647 headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
8648 headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
8649 headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
8650 headtarget += facing * 1.5;
8652 targetheadyaw = 180 - roughDirectionTo(coords, headtarget);
8653 targetheadpitch = pitchTo(coords, headtarget);