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()));
78 std::vector<PersonType> PersonType::types;
80 void PersonType::Load()
85 types[wolftype].proportions[0] = 1.1;
86 types[wolftype].proportions[1] = 1.1;
87 types[wolftype].proportions[2] = 1.1;
88 types[wolftype].proportions[3] = 1.1;
90 types[wolftype].animRun = wolfrunanim;
91 types[wolftype].animRunning = wolfrunninganim;
92 types[wolftype].animCrouch = wolfcrouchanim;
93 types[wolftype].animStop = wolfstopanim;
94 types[wolftype].animLanding = wolflandanim;
95 types[wolftype].animLandingHard = wolflandhardanim;
97 types[wolftype].soundsAttack[0] = barksound;
98 types[wolftype].soundsAttack[1] = bark2sound;
99 types[wolftype].soundsAttack[2] = bark3sound;
100 types[wolftype].soundsAttack[3] = barkgrowlsound;
101 types[wolftype].soundsTalk[0] = growlsound;
102 types[wolftype].soundsTalk[1] = growl2sound;
105 types[rabbittype].proportions[0] = 1.2;
106 types[rabbittype].proportions[1] = 1.05;
107 types[rabbittype].proportions[2] = 1;
108 types[rabbittype].proportions[3] = 1.1;
109 types[rabbittype].proportions[3].y = 1.05;
111 types[rabbittype].animRun = runanim;
112 types[rabbittype].animRunning = rabbitrunninganim;
113 types[rabbittype].animCrouch = crouchanim;
114 types[rabbittype].animStop = stopanim;
115 types[rabbittype].animLanding = landanim;
116 types[rabbittype].animLandingHard = landhardanim;
118 types[rabbittype].soundsAttack[0] = rabbitattacksound;
119 types[rabbittype].soundsAttack[1] = rabbitattack2sound;
120 types[rabbittype].soundsAttack[2] = rabbitattack3sound;
121 types[rabbittype].soundsAttack[3] = rabbitattack4sound;
122 types[rabbittype].soundsTalk[0] = rabbitchitter;
123 types[rabbittype].soundsTalk[1] = rabbitchitter2;
129 , animCurrent(bounceidleanim)
130 , animTarget(bounceidleanim)
137 , howactive(typeactive)
139 , superruntoggle(false)
173 , rabbitkickenabled(false)
187 , superpermanentdamage(0)
230 , normalsupdatedelay(0)
234 , forwardkeydown(false)
235 , forwardstogglekeydown(false)
236 , rightkeydown(false)
240 , jumptogglekeydown(false)
241 , crouchkeydown(false)
242 , crouchtogglekeydown(false)
244 , drawtogglekeydown(false)
245 , throwkeydown(false)
246 , throwtogglekeydown(false)
247 , attackkeydown(false)
269 , whichdirection(false)
270 , whichdirectiondelay(0)
271 , avoidsomething(false)
281 , lefthandmorphness(0)
282 , righthandmorphness(0)
286 , targetlefthandmorphness(0)
287 , targetrighthandmorphness(0)
288 , targetheadmorphness(1)
289 , targetchestmorphness(0)
290 , targettailmorphness(0)
291 , lefthandmorphstart(0)
292 , lefthandmorphend(0)
293 , righthandmorphstart(0)
294 , righthandmorphend(0)
304 , highreversaldelay(0)
305 , lowreversaldelay(0)
354 , weaponstuckwhere(0)
367 , finalpathfindpoint(0)
368 , targetpathfindpoint(0)
369 , lastpathfindpoint(0)
370 , lastpathfindpoint2(0)
371 , lastpathfindpoint3(0)
372 , lastpathfindpoint4(0)
392 , neckspurtparticledelay(0)
397 , rabbitkickragdoll(false)
405 setProportions(1, 1, 1, 1);
408 /* Read a person in tfile. Throws an error if it’s not valid */
409 Person::Person(FILE* tfile, int mapvers, unsigned i)
413 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
415 funpackf(tfile, "Bi", &howactive);
417 howactive = typeactive;
420 funpackf(tfile, "Bf", &scale);
425 funpackf(tfile, "Bb", &immobile);
430 funpackf(tfile, "Bf", &yaw);
435 if (num_weapons < 0 || num_weapons > 5) {
436 throw InvalidPersonException();
438 if (num_weapons > 0 && num_weapons < 5) {
439 for (int j = 0; j < num_weapons; j++) {
440 weaponids[j] = weapons.size();
442 funpackf(tfile, "Bi", &type);
443 weapons.push_back(Weapon(type, id));
446 funpackf(tfile, "Bi", &numwaypoints);
447 for (int j = 0; j < numwaypoints; j++) {
448 funpackf(tfile, "Bf", &waypoints[j].x);
449 funpackf(tfile, "Bf", &waypoints[j].y);
450 funpackf(tfile, "Bf", &waypoints[j].z);
452 funpackf(tfile, "Bi", &waypointtype[j]);
454 waypointtype[j] = wpkeepwalking;
458 funpackf(tfile, "Bi", &waypoint);
459 if (waypoint > (numwaypoints - 1)) {
463 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
464 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
465 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
466 funpackf(tfile, "Bf Bf", &power, &speedmult);
469 funpackf(tfile, "Bf Bf Bf Bf", &proportions[0], &proportions[1], &proportions[2], &proportions[3]);
471 setProportions(1, 1, 1, 1);
474 funpackf(tfile, "Bi", &numclothes);
475 for (int k = 0; k < numclothes; k++) {
477 funpackf(tfile, "Bi", &templength);
478 for (int l = 0; l < templength; l++) {
479 funpackf(tfile, "Bb", &clothes[k][l]);
481 clothes[k][templength] = '\0';
482 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
488 if (creature == wolftype) {
490 damagetolerance = 300;
497 realoldcoords = coords;
500 void Person::skeletonLoad(bool clothes)
503 if (creature != wolftype) {
505 "Skeleton/BasicFigure",
506 "Skeleton/BasicFigureLow",
507 "Skeleton/RabbitBelt",
509 "Models/Body2.solid",
510 "Models/Body3.solid",
511 "Models/Body4.solid",
512 "Models/Body5.solid",
513 "Models/Body6.solid",
514 "Models/Body7.solid",
515 "Models/BodyLow.solid",
520 "Skeleton/BasicFigureWolf",
521 "Skeleton/BasicFigureWolfLow",
522 "Skeleton/RabbitBelt",
524 "Models/Wolf2.solid",
525 "Models/Wolf3.solid",
526 "Models/Wolf4.solid",
527 "Models/Wolf5.solid",
528 "Models/Wolf6.solid",
529 "Models/Wolf7.solid",
530 "Models/WolfLow.solid",
535 skeleton.drawmodel.textureptr.load(creatureskin[creature][whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
538 void Person::setProportions(float head, float body, float arms, float legs)
540 proportions[0] = head;
541 proportions[1] = body;
542 proportions[2] = arms;
543 proportions[3] = legs;
546 XYZ Person::getProportion(int part) const
548 XYZ prop = PersonType::types[creature].proportions[part] * proportions[part];
558 * GameTick/doPlayerCollisions
560 void Person::CheckKick()
562 if (!(hasvictim && (animTarget == rabbitkickanim && victim && victim != this->shared_from_this() && frameCurrent >= 2 && animCurrent == rabbitkickanim) && distsq(&coords, &victim->coords) < 1.2 && !victim->skeleton.free)) {
566 if (Animation::animations[victim->animTarget].height != lowheight) {
567 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
568 XYZ relative = velocity;
570 Normalise(&relative);
574 if (!Tutorial::active) {
575 emit_sound_at(heavyimpactsound, victim->coords);
578 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
579 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
582 victim->DoDamage(100 * damagemult / victim->protectionhigh);
589 animTarget = backflipanim;
591 velocity = facing * -10;
595 resume_stream(whooshsound);
598 award_bonus(id, cannon);
599 } else if (victim->isCrouch()) {
600 animTarget = rabbitkickreversedanim;
601 animCurrent = rabbitkickreversedanim;
602 victim->animCurrent = rabbitkickreversalanim;
603 victim->animTarget = rabbitkickreversalanim;
609 victim->oldcoords = victim->coords;
610 coords = victim->coords;
611 victim->targetyaw = targetyaw;
612 victim->victim = this->shared_from_this();
619 * GameTick::doPlayerCollisions - spread fire between players
620 * GameTick::ProcessDevKeys - press f to ignite
621 * Person::DoStuff - spread fire from lit campfires and bushes
623 void Person::CatchFire()
625 XYZ flatfacing, flatvelocity;
627 for (int i = 0; i < 10; i++) {
628 howmany = fabs(Random() % (skeleton.joints.size()));
630 flatvelocity = skeleton.joints[howmany].velocity;
631 flatfacing = skeleton.joints[howmany].position * scale + coords;
633 flatvelocity = velocity;
634 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
636 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
641 emit_sound_at(firestartsound, coords);
643 emit_stream_at(stream_firesound, coords);
651 * idle animation for this creature (depending on status)
653 int Person::getIdle()
655 if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype)) {
658 if (hasvictim && (victim != this->shared_from_this())) {
659 if ((!victim->dead && victim->aitype != passivetype &&
660 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
661 victim->id < Person::players.size())) {
662 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
663 if (creature == rabbittype) {
664 return fightidleanim;
666 if (creature == wolftype) {
670 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
671 if (weapons[weaponids[weaponactive]].getType() == knife) {
672 return knifefightidleanim;
674 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1) {
675 return swordfightidlebothanim;
677 if (weapons[weaponids[weaponactive]].getType() == sword) {
678 return swordfightidleanim;
680 if (weapons[weaponids[weaponactive]].getType() == staff) {
681 return swordfightidleanim;
684 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause) {
685 return fightsidestep;
689 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype) {
692 if (howactive == typesitting) {
695 if (howactive == typesittingwall) {
698 if (howactive == typesleeping) {
701 if (howactive == typedead1) {
704 if (howactive == typedead2) {
707 if (howactive == typedead3) {
710 if (howactive == typedead4) {
713 if (creature == rabbittype) {
714 return bounceidleanim;
716 if (creature == wolftype) {
723 * crouch animation for this creature
725 int Person::getCrouch()
727 return PersonType::types[creature].animCrouch;
731 * running animation for this creature (can be upright or all fours)
735 if (superruntoggle && (weaponactive == -1)) {
736 return PersonType::types[creature].animRunning;
738 return PersonType::types[creature].animRun;
744 int Person::getStop()
746 return PersonType::types[creature].animStop;
751 int Person::getLanding()
753 return PersonType::types[creature].animLanding;
758 int Person::getLandhard()
760 return PersonType::types[creature].animLandingHard;
766 * Person::DoAnimations
769 SolidHitBonus(int playerid)
771 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo) {
772 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
774 award_bonus(playerid, solidhit);
779 * spawns blood effects
781 void Person::DoBlood(float howmuch, int which)
783 // FIXME: should abstract out inputs
784 static int bleedxint, bleedyint;
786 if (bloodtoggle && !Tutorial::active) {
787 if (bleeding <= 0 && spurt) {
789 for (int i = 0; i < 3; i++) {
790 // emit blood particles
793 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
794 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
795 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
796 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
799 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
800 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
801 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
802 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
805 if (Random() % 2 == 0) { // 50% chance
806 for (int i = 0; i < 3; i++) {
807 if (Random() % 2 != 0) {
808 // emit teeth particles
811 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
812 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
815 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
816 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
820 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
822 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
824 Sprite::setLastSpriteSpecial(3); // sets it to teeth
830 // FIXME: manipulating attributes
831 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
834 if (creature == rabbittype) {
835 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) {
836 bleedxint = abs(Random() % 512);
837 bleedyint = abs(Random() % 512);
840 if (creature == wolftype) {
841 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) {
842 bleedxint = abs(Random() % 512);
843 bleedyint = abs(Random() % 512);
848 bleedy /= realtexdetail;
849 bleedx /= realtexdetail;
850 direction = abs(Random() % 2) * 2 - 1;
859 * spawns big blood effects and ???
860 * modifies character's skin texture
862 void Person::DoBloodBig(float howmuch, int which)
864 static int bleedxint, bleedyint, i, j;
866 if (howmuch && id == 0) {
870 if (!Tutorial::active || id == 0) {
871 if (aitype != playercontrolled && howmuch > 0) {
875 if (creature == wolftype) {
876 int i = abs(Random() % 2);
878 whichsound = snarlsound;
881 whichsound = snarl2sound;
884 if (creature == rabbittype) {
885 int i = abs(Random() % 2);
887 whichsound = rabbitpainsound;
889 if (i == 1 && howmuch >= 2) {
890 whichsound = rabbitpain1sound;
894 if (whichsound != -1) {
895 emit_sound_at(whichsound, coords);
901 if (id == 0 && howmuch > 0) {
905 if (bloodtoggle && decalstoggle && !Tutorial::active) {
906 if (bleeding <= 0 && spurt) {
908 for (int i = 0; i < 3; i++) {
909 // emit blood particles
910 // FIXME: copypaste from above
913 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
914 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
915 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
916 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
919 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
920 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
921 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
922 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
927 // weird texture manipulation code follows.
928 // looks like this is painting blood onto the character's skin texture
929 // FIXME: surely there's a better way
931 int offsetx = 0, offsety = 0;
933 offsety = Random() % 40;
934 offsetx = abs(Random() % 60);
936 if (which == 190 || which == 185) {
937 offsety = Random() % 40;
938 offsetx = abs(Random() % 100) - 20;
941 offsety = Random() % 10;
942 offsetx = Random() % 10;
945 offsety = Random() % 20;
946 offsetx = Random() % 20;
948 if (which == 220 || which == 215) {
957 if (creature == rabbittype) {
958 for (i = 0; i < 512; i++) {
959 for (j = 0; j < 512; j++) {
960 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
977 if (creature == wolftype) {
978 for (i = 0; i < 512; i++) {
979 for (j = 0; j < 512; j++) {
980 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1009 if (endx > 512 - 1) {
1012 if (endy > 512 - 1) {
1015 if (endx < startx) {
1018 if (endy < starty) {
1022 startx /= realtexdetail;
1023 starty /= realtexdetail;
1024 endx /= realtexdetail;
1025 endy /= realtexdetail;
1027 int texdetailint = realtexdetail;
1029 if (creature == rabbittype) {
1030 for (i = startx; i < endx; i++) {
1031 for (j = starty; j < endy; j++) {
1032 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) {
1033 color = Random() % 85 + 170;
1034 where = i * skeleton.skinsize * 3 + j * 3;
1035 if (skeleton.skinText[where + 0] > color / 2) {
1036 skeleton.skinText[where + 0] = color / 2;
1038 skeleton.skinText[where + 1] = 0;
1039 skeleton.skinText[where + 2] = 0;
1044 if (creature == wolftype) {
1045 for (i = startx; i < endx; i++) {
1046 for (j = starty; j < endy; j++) {
1047 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) {
1048 color = Random() % 85 + 170;
1049 where = i * skeleton.skinsize * 3 + j * 3;
1050 if (skeleton.skinText[where + 0] > color / 2) {
1051 skeleton.skinText[where + 0] = color / 2;
1053 skeleton.skinText[where + 1] = 0;
1054 skeleton.skinText[where + 2] = 0;
1059 skeleton.drawmodel.textureptr.bind();
1064 if (creature == rabbittype) {
1065 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) {
1066 bleedxint = abs(Random() % 512);
1067 bleedyint = abs(Random() % 512);
1070 if (creature == wolftype) {
1071 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) {
1072 bleedxint = abs(Random() % 512);
1073 bleedyint = abs(Random() % 512);
1076 bleedy = bleedxint + offsetx;
1077 bleedx = bleedyint + offsety;
1078 bleedy /= realtexdetail;
1079 bleedx /= realtexdetail;
1086 if (bleedx > skeleton.skinsize - 1) {
1087 bleedx = skeleton.skinsize - 1;
1089 if (bleedy > skeleton.skinsize - 1) {
1090 bleedy = skeleton.skinsize - 1;
1092 direction = abs(Random() % 2) * 2 - 1;
1094 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1095 deathbleeding += bleeding;
1096 bloodloss += bleeding * 3;
1098 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1099 if (abs(Random() % 2) == 0) {
1100 aitype = gethelptype;
1103 aitype = attacktypecutoff;
1113 * similar to DoBloodBig
1115 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
1118 static XYZ bloodvel;
1119 static XYZ startpoint, endpoint, colpoint, movepoint;
1120 static float rotationpoint;
1121 static int whichtri;
1122 static XYZ p1, p2, p3, p0;
1125 float coordsx, coordsy;
1128 if (bloodtoggle && decalstoggle && !Tutorial::active) {
1130 if (!skeleton.free) {
1131 where = DoRotation(where, 0, -yaw, 0);
1135 startpoint.y += 100;
1140 // ray testing for a tri in the character model
1141 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
1142 if (whichtri != -1) {
1143 // low level geometry math
1145 p1 = skeleton.drawmodel.getTriangleVertex(whichtri, 0);
1146 p2 = skeleton.drawmodel.getTriangleVertex(whichtri, 1);
1147 p3 = skeleton.drawmodel.getTriangleVertex(whichtri, 2);
1149 bary.x = distsq(&p0, &p1);
1150 bary.y = distsq(&p0, &p2);
1151 bary.z = distsq(&p0, &p3);
1153 total = bary.x + bary.y + bary.z;
1158 bary.x = 1 - bary.x;
1159 bary.y = 1 - bary.y;
1160 bary.z = 1 - bary.z;
1162 total = bary.x + bary.y + bary.z;
1167 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1168 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1169 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1170 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1171 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1172 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1173 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;
1174 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;
1176 if (bleeding <= 0 && spurt) {
1178 for (int i = 0; i < 3; i++) {
1179 // emit blood particles
1180 // FIXME: more copypaste code
1182 if (skeleton.free) {
1183 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1184 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1185 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1186 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1189 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1190 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1191 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1192 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1197 // texture manipulation follows
1199 int offsetx = 0, offsety = 0;
1200 offsetx = (1 + coordsy) * 512 - 291;
1201 offsety = coordsx * 512 - 437;
1208 if (creature == rabbittype) {
1209 for (i = 0; i < 512; i++) {
1210 for (j = 0; j < 512; j++) {
1211 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1228 if (creature == wolftype) {
1229 for (i = 0; i < 512; i++) {
1230 for (j = 0; j < 512; j++) {
1231 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1259 if (endx > 512 - 1) {
1262 if (endy > 512 - 1) {
1265 if (endx < startx) {
1268 if (endy < starty) {
1272 startx /= realtexdetail;
1273 starty /= realtexdetail;
1274 endx /= realtexdetail;
1275 endy /= realtexdetail;
1277 int texdetailint = realtexdetail;
1279 if (creature == rabbittype) {
1280 for (i = startx; i < endx; i++) {
1281 for (j = starty; j < endy; j++) {
1282 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) {
1283 color = Random() % 85 + 170;
1284 where = i * skeleton.skinsize * 3 + j * 3;
1285 if (skeleton.skinText[where + 0] > color / 2) {
1286 skeleton.skinText[where + 0] = color / 2;
1288 skeleton.skinText[where + 1] = 0;
1289 skeleton.skinText[where + 2] = 0;
1290 } 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) {
1291 color = Random() % 85 + 170;
1292 where = i * skeleton.skinsize * 3 + j * 3;
1293 if (skeleton.skinText[where + 0] > color / 2) {
1294 skeleton.skinText[where + 0] = color / 2;
1296 skeleton.skinText[where + 1] = 0;
1297 skeleton.skinText[where + 2] = 0;
1302 if (creature == wolftype) {
1303 for (i = startx; i < endx; i++) {
1304 for (j = starty; j < endy; j++) {
1305 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) {
1306 color = Random() % 85 + 170;
1307 where = i * skeleton.skinsize * 3 + j * 3;
1308 if (skeleton.skinText[where + 0] > color / 2) {
1309 skeleton.skinText[where + 0] = color / 2;
1311 skeleton.skinText[where + 1] = 0;
1312 skeleton.skinText[where + 2] = 0;
1313 } 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) {
1314 color = Random() % 85 + 170;
1315 where = i * skeleton.skinsize * 3 + j * 3;
1316 if (skeleton.skinText[where + 0] > color / 2) {
1317 skeleton.skinText[where + 0] = color / 2;
1319 skeleton.skinText[where + 1] = 0;
1320 skeleton.skinText[where + 2] = 0;
1325 skeleton.drawmodel.textureptr.bind();
1328 bleedy = (1 + coordsy) * 512;
1329 bleedx = coordsx * 512;
1330 bleedy /= realtexdetail;
1331 bleedx /= realtexdetail;
1338 if (bleedx > skeleton.skinsize - 1) {
1339 bleedx = skeleton.skinsize - 1;
1341 if (bleedy > skeleton.skinsize - 1) {
1342 bleedy = skeleton.skinsize - 1;
1344 direction = abs(Random() % 2) * 2 - 1;
1346 if (whichtri == -1) {
1350 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1351 deathbleeding += bleeding;
1352 bloodloss += bleeding * 3;
1354 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1355 if (abs(Random() % 2) == 0) {
1356 aitype = gethelptype;
1359 aitype = attacktypecutoff;
1370 * guessing this performs a reversal
1372 void Person::Reverse()
1374 if (!((victim->aitype == playercontrolled || hostiletime > 1 || staggerdelay <= 0) && victim->animTarget != jumpupanim && victim->animTarget != jumpdownanim && (!Tutorial::active || cananger) && hostile)) {
1378 if (normaldotproduct(victim->facing, victim->coords - coords) > 0 && (victim->id != 0 || difficulty >= 2) && (creature != wolftype || victim->creature == wolftype)) {
1382 if (animTarget == sweepanim) {
1383 animTarget = sweepreversedanim;
1384 animCurrent = sweepreversedanim;
1385 victim->animCurrent = sweepreversalanim;
1386 victim->animTarget = sweepreversalanim;
1388 if (animTarget == spinkickanim) {
1389 animTarget = spinkickreversedanim;
1390 animCurrent = spinkickreversedanim;
1391 victim->animCurrent = spinkickreversalanim;
1392 victim->animTarget = spinkickreversalanim;
1394 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1395 if (animTarget == rabbittacklinganim) {
1398 victim->frameCurrent = 6;
1399 victim->frameTarget = 7;
1401 animTarget = upunchreversedanim;
1402 animCurrent = upunchreversedanim;
1403 victim->animCurrent = upunchreversalanim;
1404 victim->animTarget = upunchreversalanim;
1406 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1407 if (victim->weaponactive != -1) {
1408 victim->throwtogglekeydown = 1;
1409 XYZ tempVelocity = victim->velocity * .2;
1410 if (tempVelocity.x == 0) {
1411 tempVelocity.x = .1;
1413 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1414 victim->num_weapons--;
1415 if (victim->num_weapons) {
1416 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1417 if (victim->weaponstuck == victim->num_weapons) {
1418 victim->weaponstuck = 0;
1422 victim->weaponactive = -1;
1423 for (unsigned j = 0; j < Person::players.size(); j++) {
1424 Person::players[j]->wentforweapon = 0;
1428 animTarget = staffhitreversedanim;
1429 animCurrent = staffhitreversedanim;
1430 victim->animCurrent = staffhitreversalanim;
1431 victim->animTarget = staffhitreversalanim;
1433 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1434 if (victim->weaponactive != -1) {
1435 victim->throwtogglekeydown = 1;
1436 XYZ tempVelocity = victim->velocity * .2;
1437 if (tempVelocity.x == 0) {
1438 tempVelocity.x = .1;
1440 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1441 victim->num_weapons--;
1442 if (victim->num_weapons) {
1443 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1444 if (victim->weaponstuck == victim->num_weapons) {
1445 victim->weaponstuck = 0;
1449 victim->weaponactive = -1;
1450 for (unsigned j = 0; j < Person::players.size(); j++) {
1451 Person::players[j]->wentforweapon = 0;
1454 animTarget = staffspinhitreversedanim;
1455 animCurrent = staffspinhitreversedanim;
1456 victim->animCurrent = staffspinhitreversalanim;
1457 victim->animTarget = staffspinhitreversalanim;
1459 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1460 if (victim->weaponactive != -1) {
1461 victim->throwtogglekeydown = 1;
1462 XYZ tempVelocity = victim->velocity * .2;
1463 if (tempVelocity.x == 0) {
1464 tempVelocity.x = .1;
1466 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1467 victim->num_weapons--;
1468 if (victim->num_weapons) {
1469 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1470 if (victim->weaponstuck == victim->num_weapons) {
1471 victim->weaponstuck = 0;
1475 victim->weaponactive = -1;
1476 for (unsigned j = 0; j < Person::players.size(); j++) {
1477 Person::players[j]->wentforweapon = 0;
1480 animTarget = swordslashreversedanim;
1481 animCurrent = swordslashreversedanim;
1482 victim->animCurrent = swordslashreversalanim;
1483 victim->animTarget = swordslashreversalanim;
1485 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1486 if (victim->weaponactive != -1) {
1487 victim->throwtogglekeydown = 1;
1488 XYZ tempVelocity = victim->velocity * .2;
1489 if (tempVelocity.x == 0) {
1490 tempVelocity.x = .1;
1492 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1493 victim->num_weapons--;
1494 if (victim->num_weapons) {
1495 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1496 if (victim->weaponstuck == victim->num_weapons) {
1497 victim->weaponstuck = 0;
1501 victim->weaponactive = -1;
1502 for (unsigned j = 0; j < Person::players.size(); j++) {
1503 Person::players[j]->wentforweapon = 0;
1506 animTarget = knifeslashreversedanim;
1507 animCurrent = knifeslashreversedanim;
1508 victim->animCurrent = knifeslashreversalanim;
1509 victim->animTarget = knifeslashreversalanim;
1511 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1512 victim->targettilt2 = targettilt2;
1513 victim->frameCurrent = frameCurrent;
1514 victim->frameTarget = frameTarget;
1515 victim->target = target;
1516 victim->velocity = 0;
1517 victim->oldcoords = victim->coords;
1518 victim->coords = coords;
1519 victim->targetyaw = targetyaw;
1520 victim->yaw = targetyaw;
1521 victim->victim = this->shared_from_this();
1523 if (animTarget == winduppunchanim) {
1524 animTarget = winduppunchblockedanim;
1525 victim->animTarget = blockhighleftanim;
1526 victim->frameTarget = 1;
1527 victim->target = .5;
1528 victim->victim = this->shared_from_this();
1529 victim->targetyaw = targetyaw + 180;
1531 if (animTarget == wolfslapanim) {
1532 animTarget = winduppunchblockedanim;
1533 victim->animTarget = blockhighleftanim;
1534 victim->frameTarget = 1;
1535 victim->target = .5;
1536 victim->victim = this->shared_from_this();
1537 victim->targetyaw = targetyaw + 180;
1539 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1540 animTarget = swordslashparriedanim;
1541 parriedrecently = .4;
1542 victim->parriedrecently = 0;
1543 victim->animTarget = swordslashparryanim;
1544 victim->frameTarget = 1;
1545 victim->target = .5;
1546 victim->victim = this->shared_from_this();
1547 victim->targetyaw = targetyaw + 180;
1549 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1550 if (victim->weaponactive != -1) {
1551 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1552 if (weapons[victim->weaponids[0]].getType() == staff) {
1553 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1555 if (weapons[weaponids[0]].getType() == staff) {
1556 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1558 emit_sound_at(swordstaffsound, victim->coords);
1560 emit_sound_at(metalhitsound, victim->coords);
1564 victim->Puff(righthand);
1566 victim->frameTarget = 0;
1567 victim->animTarget = staggerbackhighanim;
1568 victim->targetyaw = targetyaw + 180;
1570 aim = DoRotation(facing, 0, 90, 0) * 21;
1572 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1573 victim->num_weapons--;
1574 if (victim->num_weapons) {
1575 victim->weaponids[0] = victim->weaponids[num_weapons];
1576 if (victim->weaponstuck == victim->num_weapons) {
1577 victim->weaponstuck = 0;
1580 victim->weaponactive = -1;
1581 for (unsigned i = 0; i < Person::players.size(); i++) {
1582 Person::players[i]->wentforweapon = 0;
1586 if (abs(Random() % 20) == 0) {
1587 if (weaponactive != -1) {
1588 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1589 if (weapons[victim->weaponids[0]].getType() == staff) {
1590 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1592 if (weapons[weaponids[0]].getType() == staff) {
1593 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1596 emit_sound_at(swordstaffsound, coords);
1598 emit_sound_at(metalhitsound, coords);
1606 animTarget = staggerbackhighanim;
1607 targetyaw = targetyaw + 180;
1609 aim = DoRotation(facing, 0, 90, 0) * 21;
1611 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1614 weaponids[0] = weaponids[num_weapons];
1615 if (weaponstuck == num_weapons) {
1620 for (unsigned i = 0; i < Person::players.size(); i++) {
1621 Person::players[i]->wentforweapon = 0;
1626 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1627 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1628 victim->animTarget = dodgebackanim;
1629 victim->frameTarget = 0;
1633 rotatetarget = coords - victim->coords;
1634 Normalise(&rotatetarget);
1635 victim->targetyaw = -asin(0 - rotatetarget.x);
1636 victim->targetyaw *= 360 / 6.28;
1637 if (rotatetarget.z < 0) {
1638 victim->targetyaw = 180 - victim->targetyaw;
1641 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1643 victim->lastattack3 = victim->lastattack2;
1644 victim->lastattack2 = victim->lastattack;
1645 victim->lastattack = victim->animTarget;
1647 victim->animTarget = sweepanim;
1648 victim->frameTarget = 0;
1652 rotatetarget = coords - victim->coords;
1653 Normalise(&rotatetarget);
1654 victim->targetyaw = -asin(0 - rotatetarget.x);
1655 victim->targetyaw *= 360 / 6.28;
1656 if (rotatetarget.z < 0) {
1657 victim->targetyaw = 180 - victim->targetyaw;
1660 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1662 victim->lastattack3 = victim->lastattack2;
1663 victim->lastattack2 = victim->lastattack;
1664 victim->lastattack = victim->animTarget;
1670 victim->velocity = 0;
1672 if (aitype != playercontrolled) {
1674 if (escapednum < 2) {
1675 int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
1676 if ((Random() % chances) == 0) {
1682 if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal) {
1690 void Person::DoDamage(float howmuch)
1694 damagetaken += howmuch / power;
1696 damagedealt += howmuch / power;
1700 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo)) {
1705 if (!Tutorial::active) {
1706 damage += howmuch / power;
1707 permanentdamage += howmuch / 2 / power;
1708 superpermanentdamage += howmuch / 4 / power;
1711 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2) {
1714 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt) {
1719 camerashake += howmuch / 100;
1720 if ((howmuch > 50 && damage > damagetolerance / 2)) {
1721 blackout = damage / damagetolerance;
1729 if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile)) {
1730 aitype = attacktypecutoff;
1732 if (!Tutorial::active && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1733 if (abs(Random() % 2) == 0) {
1734 aitype = gethelptype;
1737 aitype = attacktypecutoff;
1742 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1745 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1746 if (skeleton.free) {
1747 flatvelocity2 = skeleton.joints[i].velocity;
1748 flatfacing2 = skeleton.joints[i].position * scale + coords;
1750 flatvelocity2 = velocity;
1751 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1753 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1754 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1755 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1756 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1757 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1758 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1761 emit_sound_at(splattersound, coords);
1766 if (!dead && creature == wolftype) {
1767 award_bonus(0, Wolfbonus);
1774 if (!Tutorial::active || id == 0) {
1775 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1776 int whichsound = -1;
1778 if (creature == wolftype) {
1779 int i = abs(Random() % 2);
1781 whichsound = snarlsound;
1784 whichsound = snarl2sound;
1787 if (creature == rabbittype) {
1788 int i = abs(Random() % 2);
1790 whichsound = rabbitpainsound;
1792 if (i == 1 && damage > damagetolerance) {
1793 whichsound = rabbitpain1sound;
1797 if (whichsound != -1) {
1798 emit_sound_at(whichsound, coords);
1799 addEnvSound(coords);
1807 * calculate/animate head facing direction?
1809 void Person::DoHead()
1811 static XYZ rotatearound;
1813 static float lookspeed = 500;
1815 if (!freeze && !winfreeze) {
1818 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1819 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1821 while (targetheadyaw > 180) {
1822 targetheadyaw -= 360;
1824 while (targetheadyaw < -180) {
1825 targetheadyaw += 360;
1828 if (targetheadyaw > 160) {
1829 targetheadpitch = targetheadpitch * -1;
1831 if (targetheadyaw < -160) {
1832 targetheadpitch = targetheadpitch * -1;
1834 if (targetheadyaw > 160) {
1835 targetheadyaw = targetheadyaw - 180;
1837 if (targetheadyaw < -160) {
1838 targetheadyaw = targetheadyaw + 180;
1841 if (targetheadpitch > 120) {
1842 targetheadpitch = 120;
1844 if (targetheadpitch < -120) {
1845 targetheadpitch = -120;
1847 if (targetheadyaw > 120) {
1848 targetheadyaw = 120;
1850 if (targetheadyaw < -120) {
1851 targetheadyaw = -120;
1855 targetheadpitch = 0;
1858 if (targetheadyaw > 80) {
1861 if (targetheadyaw < -80) {
1862 targetheadyaw = -80;
1864 if (targetheadpitch > 50) {
1865 targetheadpitch = 50;
1867 if (targetheadpitch < -50) {
1868 targetheadpitch = -50;
1872 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed) {
1873 headyaw = targetheadyaw;
1874 } else if (headyaw > targetheadyaw) {
1875 headyaw -= multiplier * lookspeed;
1876 } else if (headyaw < targetheadyaw) {
1877 headyaw += multiplier * lookspeed;
1880 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2) {
1881 headpitch = targetheadpitch;
1882 } else if (headpitch > targetheadpitch) {
1883 headpitch -= multiplier * lookspeed / 2;
1884 } else if (headpitch < targetheadpitch) {
1885 headpitch += multiplier * lookspeed / 2;
1888 rotatearound = jointPos(neck);
1889 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1893 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1894 facing = DoRotation(facing, headpitch * .4, 0, 0);
1895 facing = DoRotation(facing, 0, headyaw * .4, 0);
1898 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1899 facing = DoRotation(facing, headpitch * .8, 0, 0);
1900 facing = DoRotation(facing, 0, headyaw * .8, 0);
1903 if (animTarget == walkanim) {
1904 facing = DoRotation(facing, headpitch * .6, 0, 0);
1905 facing = DoRotation(facing, 0, headyaw * .6, 0);
1908 skeleton.specialforward[0] = facing;
1909 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1910 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
1911 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1912 skeleton.FindRotationMuscle(i, animTarget);
1919 * ragdolls character?
1921 void Person::RagDoll(bool checkcollision)
1926 if (!skeleton.free) {
1930 if (id == 0 && isFlip()) {
1938 facing = DoRotation(facing, 0, yaw, 0);
1940 skeleton.freetime = 0;
1942 skeleton.longdead = 0;
1945 skeleton.broken = 0;
1946 skeleton.spinny = 1;
1948 skeleton.freefall = 1;
1950 if (!isnormal(velocity.x)) {
1953 if (!isnormal(velocity.y)) {
1956 if (!isnormal(velocity.z)) {
1959 if (!isnormal(yaw)) {
1962 if (!isnormal(coords.x)) {
1965 if (!isnormal(tilt)) {
1968 if (!isnormal(tilt2)) {
1972 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1973 skeleton.joints[i].delay = 0;
1974 skeleton.joints[i].locked = 0;
1975 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1976 if (!isnormal(skeleton.joints[i].position.x)) {
1977 skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1979 if (!isnormal(skeleton.joints[i].position.x)) {
1980 skeleton.joints[i].position = coords;
1982 skeleton.joints[i].position.y += .1;
1983 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1984 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1987 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1988 skeleton.joints[i].velocity = 0;
1989 skeleton.joints[i].velchange = 0;
1991 skeleton.DoConstraints(&coords, &scale);
1992 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
1993 skeleton.DoConstraints(&coords, &scale);
1994 skeleton.DoConstraints(&coords, &scale);
1995 skeleton.DoConstraints(&coords, &scale);
1996 skeleton.DoConstraints(&coords, &scale);
1999 speed = targetFrame().speed * 2;
2000 if (currentFrame().speed > targetFrame().speed) {
2001 speed = currentFrame().speed * 2;
2004 speed = transspeed * 2;
2009 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
2010 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height) {
2011 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);
2013 skeleton.joints[i].velocity = velocity / scale + facing * 5;
2015 change.x = (float)(Random() % 100) / 100;
2016 change.y = (float)(Random() % 100) / 100;
2017 change.z = (float)(Random() % 100) / 100;
2018 skeleton.joints[i].velocity += change;
2019 skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change;
2021 change.x = (float)(Random() % 100) / 100;
2022 change.y = (float)(Random() % 100) / 100;
2023 change.z = (float)(Random() % 100) / 100;
2024 skeleton.joints[i].velchange += change;
2025 skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change;
2028 if (checkcollision) {
2031 if (!skeleton.joints.empty()) {
2034 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
2035 average += skeleton.joints[j].position;
2037 average /= skeleton.joints.size();
2038 coords += average * scale;
2039 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
2040 skeleton.joints[j].position -= average;
2044 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
2045 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
2046 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
2047 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
2050 if (SphereCheck(&lowpoint, 3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
2051 coords.x = lowpoint.x;
2052 coords.z = lowpoint.z;
2061 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
2062 velocity += skeleton.joints[i].velocity * scale;
2064 velocity /= skeleton.joints.size();
2067 if (Random() % 2 == 0) {
2068 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
2069 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
2070 weapons[weaponids[0]].velocity.x += .01;
2073 weaponids[0] = weaponids[num_weapons];
2074 if (weaponstuck == num_weapons) {
2079 for (unsigned i = 0; i < Person::players.size(); i++) {
2080 Person::players[i]->wentforweapon = 0;
2085 animTarget = bounceidleanim;
2086 animCurrent = bounceidleanim;
2094 void Person::FootLand(bodypart whichfoot, float opacity)
2096 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
2097 cerr << "FootLand called on wrong bodypart" << endl;
2100 static XYZ terrainlight;
2101 static XYZ footvel, footpoint;
2102 if (opacity >= 1 || skiddelay <= 0) {
2105 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2106 if (distsq(&footpoint, &viewer)) {
2107 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
2109 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
2110 footvel = velocity / 5;
2111 if (footvel.y < .8) {
2114 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2115 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
2116 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
2117 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
2118 if (environment == snowyenvironment) {
2119 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
2121 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
2123 } else if (environment == grassyenvironment) {
2124 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
2125 } else if (environment == desertenvironment) {
2126 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
2128 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
2132 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
2133 footvel = velocity / 5;
2134 if (footvel.y < .8) {
2137 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2138 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
2139 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
2146 * make a puff effect at a body part (dust effect?)
2148 void Person::Puff(int whichlabel)
2150 static XYZ footvel, footpoint;
2153 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
2154 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
2158 * I think I added this in an attempt to clean up code
2160 void Person::setTargetAnimation(int animation)
2162 animTarget = animation;
2171 void Person::DoAnimations()
2173 if (!skeleton.free) {
2174 static float oldtarget;
2176 if (isIdle() && animCurrent != getIdle()) {
2177 normalsupdatedelay = 0;
2180 if (animTarget == tempanim || animCurrent == tempanim) {
2181 Animation::animations[tempanim] = tempanimation;
2183 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
2190 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
2191 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
2193 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z)) {
2196 if (!crouchkeydown && velocity.y >= -15) {
2200 if ((animCurrent == jumpupanim || animTarget == jumpdownanim) /*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
2205 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
2207 if (normaldotproduct(targfacing, velocity) >= -.3) {
2208 animTarget = flipanim;
2210 animTarget = backflipanim;
2212 crouchtogglekeydown = 1;
2221 if (Animation::animations[animTarget].attack != reversed) {
2224 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
2225 crouchtogglekeydown = 0;
2226 if (aitype == playercontrolled) {
2230 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain)) {
2234 crouchtogglekeydown = 1;
2238 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
2240 normalsupdatedelay = 0;
2245 if (animTarget == rollanim && frameTarget == 3 && onfire) {
2247 emit_sound_at(fireendsound, coords);
2248 pause_sound(stream_firesound);
2252 if (animTarget == rabbittacklinganim && frameTarget == 1) {
2253 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0) {
2256 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
2257 if (normaldotproduct(victim->facing, facing) > 0) {
2258 victim->animTarget = rabbittackledbackanim;
2260 victim->animTarget = rabbittackledfrontanim;
2262 victim->frameTarget = 2;
2265 victim->targetyaw = yaw;
2266 if (victim->aitype == gethelptype) {
2267 victim->DoDamage(victim->damagetolerance - victim->damage);
2269 //victim->DoDamage(30);
2270 if (creature == wolftype) {
2272 emit_sound_at(clawslicesound, victim->coords);
2274 victim->DoBloodBig(1 / victim->armorhead, 210);
2276 award_bonus(id, TackleBonus,
2277 victim->aitype == gethelptype ? 50 : 0);
2281 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2282 if (weapons[weaponids[0]].getType() == knife) {
2283 if (weaponactive == -1) {
2285 } else if (weaponactive == 0) {
2289 if (weaponactive == -1) {
2290 emit_sound_at(knifesheathesound, coords);
2292 if (weaponactive != -1) {
2293 emit_sound_at(knifedrawsound, coords, 128);
2296 drawtogglekeydown = 1;
2299 if (!Tutorial::active || id == 0) {
2300 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2301 int whichsound = -1;
2303 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2304 if (targetFrame().label == 1) {
2305 whichsound = footstepsound;
2307 whichsound = footstepsound2;
2309 if (targetFrame().label == 1) {
2310 FootLand(leftfoot, 1);
2312 if (targetFrame().label == 2) {
2313 FootLand(rightfoot, 1);
2315 if (targetFrame().label == 3 && isRun()) {
2316 FootLand(rightfoot, 1);
2317 FootLand(leftfoot, 1);
2320 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2321 if (targetFrame().label == 1) {
2322 whichsound = footstepsound3;
2324 whichsound = footstepsound4;
2329 if (targetFrame().label == 1) {
2330 whichsound = footstepsound3;
2332 whichsound = footstepsound4;
2335 if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2336 if (Animation::animations[animTarget].attack != neutral) {
2337 unsigned r = abs(Random() % 3);
2339 whichsound = lowwhooshsound;
2342 whichsound = midwhooshsound;
2345 whichsound = highwhooshsound;
2348 if (Animation::animations[animTarget].attack == neutral) {
2349 whichsound = movewhooshsound;
2351 } else if (targetFrame().label == 4) {
2352 whichsound = knifeswishsound;
2354 if (targetFrame().label == 8 && !Tutorial::active) {
2355 whichsound = landsound2;
2358 if (whichsound != -1) {
2359 emit_sound_at(whichsound, coords, 256.);
2362 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2363 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2364 addEnvSound(coords, 15);
2366 addEnvSound(coords, 6);
2371 if (targetFrame().label == 3) {
2373 emit_sound_at(whichsound, coords, 128.);
2380 if (!Tutorial::active || id == 0) {
2381 if (speechdelay <= 0) {
2382 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
2383 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2384 int whichsound = -1;
2385 if (targetFrame().label == 4 && aitype != playercontrolled) {
2386 if (Animation::animations[animTarget].attack != neutral) {
2387 unsigned r = abs(Random() % 4);
2388 whichsound = PersonType::types[creature].soundsAttack[r];
2393 if (whichsound != -1) {
2394 emit_sound_at(whichsound, coords);
2401 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2402 FootLand(leftfoot, 1);
2403 FootLand(rightfoot, 1);
2407 currentoffset = targetoffset;
2408 frameTarget = frameCurrent;
2409 animCurrent = animTarget;
2412 if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2413 for (unsigned i = 0; i < weapons.size(); i++) {
2414 if (weapons[i].owner == -1) {
2415 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2416 if (distsq(&coords, &weapons[i].position) >= 1) {
2417 if (weapons[i].getType() != staff) {
2418 emit_sound_at(knifedrawsound, coords, 128.);
2428 if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2429 for (unsigned i = 0; i < weapons.size(); i++) {
2430 bool willwork = true;
2431 if (weapons[i].owner != -1) {
2432 if (Person::players[weapons[i].owner]->weaponstuck != -1) {
2433 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i)) {
2434 if (Person::players[weapons[i].owner]->num_weapons > 1) {
2440 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free)) {
2441 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2442 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2443 bool fleshstuck = false;
2444 if (weapons[i].owner != -1) {
2445 if (victim->weaponstuck != -1) {
2446 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2452 emit_sound_at(fleshstabremovesound, coords, 128.);
2454 if (weapons[i].getType() != staff) {
2455 emit_sound_at(knifedrawsound, coords, 128.);
2458 if (weapons[i].owner != -1) {
2459 victim = Person::players[weapons[i].owner];
2460 if (victim->num_weapons == 1) {
2461 victim->num_weapons = 0;
2463 victim->num_weapons = 1;
2466 //victim->weaponactive=-1;
2467 victim->skeleton.longdead = 0;
2468 victim->skeleton.free = 1;
2469 victim->skeleton.broken = 0;
2471 for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) {
2472 victim->skeleton.joints[j].velchange = 0;
2473 victim->skeleton.joints[j].locked = 0;
2479 Normalise(&relative);
2480 XYZ footvel, footpoint;
2482 footpoint = weapons[i].position;
2483 if (victim->weaponstuck != -1) {
2484 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2486 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2488 weapons[i].bloody = 2;
2489 weapons[i].blooddrip = 5;
2490 victim->weaponstuck = -1;
2493 if (victim->num_weapons > 0) {
2494 if (victim->weaponstuck != 0 && victim->weaponstuck != -1) {
2495 victim->weaponstuck = 0;
2497 if (victim->weaponids[0] == int(i)) {
2498 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2502 victim->jointVel(abdomen) += relative * 6;
2503 victim->jointVel(neck) += relative * 6;
2504 victim->jointVel(rightshoulder) += relative * 6;
2505 victim->jointVel(leftshoulder) += relative * 6;
2514 if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2515 if (weaponactive == -1) {
2517 } else if (weaponactive == 0) {
2519 if (num_weapons == 2) {
2521 buffer = weaponids[0];
2522 weaponids[0] = weaponids[1];
2523 weaponids[1] = buffer;
2526 if (weaponactive == -1) {
2527 emit_sound_at(knifesheathesound, coords, 128.);
2529 if (weaponactive != -1) {
2530 emit_sound_at(knifedrawsound, coords, 128.);
2534 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2535 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2536 Normalise(&rotatetarget);
2537 targetyaw = -asin(0 - rotatetarget.x);
2538 targetyaw *= 360 / 6.28;
2539 if (rotatetarget.z < 0) {
2540 targetyaw = 180 - targetyaw;
2543 if (animTarget == walljumprightkickanim) {
2546 if (animTarget == walljumpleftkickanim) {
2553 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0)) {
2557 if (distsq(&victim->coords, &/*Person::players[i]->*/ coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1) {
2565 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2566 animTarget = rabbittackleanim;
2568 emit_sound_at(jumpsound, coords);
2576 targetloc = velocity;
2577 Normalise(&targetloc);
2578 targetloc += coords;
2579 for (unsigned i = 0; i < Person::players.size(); i++) {
2581 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2582 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2587 if (closestid != -1) {
2588 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2590 victim = Person::players[closestid];
2591 coords = victim->coords;
2592 animCurrent = rabbittacklinganim;
2593 animTarget = rabbittacklinganim;
2597 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2598 rotatetarget = coords - victim->coords;
2599 Normalise(&rotatetarget);
2600 targetyaw = -asin(0 - rotatetarget.x);
2601 targetyaw *= 360 / 6.28;
2602 if (rotatetarget.z < 0) {
2603 targetyaw = 180 - targetyaw;
2606 if (animTarget != rabbitrunninganim) {
2607 emit_sound_at(jumpsound, coords, 128.);
2614 float damagemult = 1 * power;
2615 if (creature == wolftype) {
2616 damagemult = 2.5 * power;
2619 damagemult /= victim->damagetolerance / 200;
2621 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)) {
2622 if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2623 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2628 if (Random() % 2 || creature == wolftype) {
2631 if (creature == wolftype) {
2635 if (!Tutorial::active) {
2636 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2638 if (creature == wolftype) {
2639 emit_sound_at(clawslicesound, victim->coords, 128.);
2641 victim->DoBloodBig(2 / victim->armorhead, 175);
2645 relative = victim->coords - coords;
2647 Normalise(&relative);
2648 relative = DoRotation(relative, 0, -90, 0);
2649 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2650 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2652 victim->jointVel(head) += relative * damagemult * 200;
2654 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2660 if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2661 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2666 if (Random() % 2 || creature == wolftype) {
2668 if (creature == wolftype) {
2672 emit_sound_at(whooshhitsound, victim->coords);
2673 if (creature == wolftype) {
2674 emit_sound_at(clawslicesound, victim->coords, 128.);
2676 victim->DoBloodBig(2, 175);
2680 relative = victim->coords - coords;
2682 Normalise(&relative);
2684 Normalise(&relative);
2685 relative = DoRotation(relative, 0, 90, 0);
2686 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2687 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2689 victim->jointVel(head) += relative * damagemult * 100;
2691 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2695 if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2696 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2703 if (!Tutorial::active) {
2704 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2706 if (creature == wolftype) {
2707 emit_sound_at(clawslicesound, victim->coords, 128.);
2709 victim->DoBloodBig(2 / victim->armorhead, 175);
2715 Normalise(&relative);
2716 relative = DoRotation(relative, 0, -90, 0);
2717 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2718 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2720 victim->jointVel(head) += relative * damagemult * 200;
2722 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2724 if (victim->damage > victim->damagetolerance) {
2725 award_bonus(id, style);
2732 if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2733 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2740 if (!Tutorial::active) {
2741 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2743 if (creature == wolftype) {
2744 emit_sound_at(clawslicesound, victim->coords, 128.);
2746 victim->DoBloodBig(2 / victim->armorhead, 175);
2752 Normalise(&relative);
2753 relative = DoRotation(relative, 0, 90, 0);
2754 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2755 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2757 victim->jointVel(head) += relative * damagemult * 200;
2759 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2761 if (victim->damage > victim->damagetolerance) {
2762 award_bonus(id, style);
2769 if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2770 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2779 emit_sound_at(whooshhitsound, victim->coords);
2782 relative = victim->coords - coords;
2784 Normalise(&relative);
2785 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2786 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2788 victim->jointVel(head) += relative * damagemult * 100;
2790 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2794 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
2795 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2800 emit_sound_at(whooshhitsound, victim->coords, 128.);
2802 victim->skeleton.longdead = 0;
2803 victim->skeleton.free = 1;
2804 victim->skeleton.broken = 0;
2805 victim->skeleton.spinny = 1;
2807 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2808 victim->skeleton.joints[i].velchange = 0;
2809 victim->skeleton.joints[i].delay = 0;
2810 victim->skeleton.joints[i].locked = 0;
2811 //victim->skeleton.joints[i].velocity=0;
2817 Normalise(&relative);
2818 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2819 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2820 victim->skeleton.joints[i].position.y += relative.y * .3;
2821 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2822 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2824 victim->Puff(abdomen);
2825 victim->jointVel(abdomen).y = relative.y * 400;
2829 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2830 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2835 if (!Tutorial::active) {
2836 emit_sound_at(heavyimpactsound, coords, 128.);
2839 relative = victim->coords - coords;
2841 Normalise(&relative);
2842 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2843 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2845 victim->Puff(abdomen);
2846 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2850 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2851 victim->jointVel(abdomen) += relative * damagemult * 300;
2855 if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
2856 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2861 if (!Tutorial::active) {
2862 emit_sound_at(thudsound, coords);
2865 victim->skeleton.longdead = 0;
2866 victim->skeleton.free = 1;
2867 victim->skeleton.broken = 0;
2868 victim->skeleton.spinny = 1;
2870 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2871 victim->skeleton.joints[i].velchange = 0;
2872 //victim->skeleton.joints[i].delay=0;
2873 victim->skeleton.joints[i].locked = 0;
2876 relative = victim->coords - coords;
2877 Normalise(&relative);
2879 Normalise(&relative);
2880 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2881 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2883 if (!victim->dead) {
2887 victim->Puff(abdomen);
2888 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2889 victim->jointVel(abdomen) += relative * damagemult * 200;
2891 if (!victim->dead) {
2897 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2900 if (!victim->skeleton.free) {
2906 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2907 emit_sound_at(knifesheathesound, coords, 128.);
2910 if (victim && hasvictim) {
2911 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2913 XYZ where, startpoint, endpoint, movepoint, colpoint;
2914 float rotationpoint;
2916 if (weapons[weaponids[weaponactive]].getType() == knife) {
2917 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2918 where -= victim->coords;
2919 if (!victim->skeleton.free) {
2920 where = DoRotation(where, 0, -victim->yaw, 0);
2924 startpoint.y += 100;
2928 if (weapons[weaponids[weaponactive]].getType() == sword) {
2929 where = weapons[weaponids[weaponactive]].position;
2930 where -= victim->coords;
2931 if (!victim->skeleton.free) {
2932 where = DoRotation(where, 0, -victim->yaw, 0);
2935 where = weapons[weaponids[weaponactive]].tippoint;
2936 where -= victim->coords;
2937 if (!victim->skeleton.free) {
2938 where = DoRotation(where, 0, -victim->yaw, 0);
2942 if (weapons[weaponids[weaponactive]].getType() == staff) {
2943 where = weapons[weaponids[weaponactive]].position;
2944 where -= victim->coords;
2945 if (!victim->skeleton.free) {
2946 where = DoRotation(where, 0, -victim->yaw, 0);
2949 where = weapons[weaponids[weaponactive]].tippoint;
2950 where -= victim->coords;
2951 if (!victim->skeleton.free) {
2952 where = DoRotation(where, 0, -victim->yaw, 0);
2958 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2960 if (whichtri != -1) {
2961 if (victim->dead != 2) {
2962 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2963 if (!victim->dead) {
2964 award_bonus(id, FinishedBonus);
2968 weapons[weaponids[weaponactive]].bloody = 2;
2971 victim->skeleton.longdead = 0;
2972 victim->skeleton.free = 1;
2973 victim->skeleton.broken = 0;
2975 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2976 victim->skeleton.joints[i].velchange = 0;
2977 victim->skeleton.joints[i].locked = 0;
2978 //victim->skeleton.joints[i].velocity=0;
2980 emit_sound_at(fleshstabsound, coords, 128);
2982 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2983 weapons[weaponids[weaponactive]].blooddrip += 5;
2984 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2986 if (whichtri == -1) {
2988 emit_sound_at(knifesheathesound, coords, 128.);
2994 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
2996 emit_sound_at(knifedrawsound, coords, 128);
2999 if (victim && hasvictim) {
3000 XYZ footvel, footpoint;
3002 emit_sound_at(fleshstabremovesound, coords, 128.);
3005 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
3007 if (weapons[weaponids[weaponactive]].getType() == sword) {
3008 XYZ where, startpoint, endpoint, movepoint;
3009 float rotationpoint;
3012 where = weapons[weaponids[weaponactive]].position;
3013 where -= victim->coords;
3014 if (!victim->skeleton.free) {
3015 where = DoRotation(where, 0, -victim->yaw, 0);
3018 where = weapons[weaponids[weaponactive]].tippoint;
3019 where -= victim->coords;
3020 if (!victim->skeleton.free) {
3021 where = DoRotation(where, 0, -victim->yaw, 0);
3027 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
3028 footpoint += victim->coords;
3030 if (whichtri == -1) {
3031 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
3034 if (weapons[weaponids[weaponactive]].getType() == staff) {
3035 XYZ where, startpoint, endpoint, movepoint;
3036 float rotationpoint;
3039 where = weapons[weaponids[weaponactive]].position;
3040 where -= victim->coords;
3041 if (!victim->skeleton.free) {
3042 where = DoRotation(where, 0, -victim->yaw, 0);
3045 where = weapons[weaponids[weaponactive]].tippoint;
3046 where -= victim->coords;
3047 if (!victim->skeleton.free) {
3048 where = DoRotation(where, 0, -victim->yaw, 0);
3054 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
3055 footpoint += victim->coords;
3057 if (whichtri == -1) {
3058 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
3061 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
3063 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
3064 victim->skeleton.longdead = 0;
3065 victim->skeleton.free = 1;
3066 victim->skeleton.broken = 0;
3068 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3069 victim->skeleton.joints[i].velchange = 0;
3070 victim->skeleton.joints[i].locked = 0;
3071 //victim->skeleton.joints[i].velocity=0;
3077 Normalise(&relative);
3078 //victim->Puff(abdomen);
3080 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
3083 if (victim->bloodloss < victim->damagetolerance) {
3084 victim->bloodloss += 1000;
3088 victim->jointVel(abdomen) += relative * damagemult * 20;
3092 if (!hasvictim && onterrain) {
3093 weapons[weaponids[weaponactive]].bloody = 0;
3094 weapons[weaponids[weaponactive]].blooddrip = 0;
3098 if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3099 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
3108 if (!Tutorial::active) {
3109 emit_sound_at(heavyimpactsound, victim->coords, 128);
3114 relative = victim->coords - coords;
3116 Normalise(&relative);
3117 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3118 victim->skeleton.joints[i].velocity = relative * 30;
3120 victim->jointVel(head) += relative * damagemult * 150;
3122 victim->frameTarget = 0;
3123 victim->animTarget = staggerbackhardanim;
3124 victim->targetyaw = targetyaw + 180;
3126 victim->stunned = 1;
3129 victim->Puff(abdomen);
3130 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
3136 if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3137 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
3142 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
3143 if (!Tutorial::active) {
3144 emit_sound_at(thudsound, victim->coords);
3146 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
3147 if (!Tutorial::active) {
3148 emit_sound_at(whooshhitsound, victim->coords);
3151 if (!Tutorial::active) {
3152 emit_sound_at(heavyimpactsound, victim->coords);
3156 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight) {
3160 relative = victim->coords - coords;
3162 Normalise(&relative);
3164 Normalise(&relative);
3165 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3166 victim->skeleton.joints[i].velocity = relative * 5;
3168 victim->jointVel(abdomen) += relative * damagemult * 400;
3170 victim->frameTarget = 0;
3171 victim->animTarget = staggerbackhardanim;
3172 victim->targetyaw = targetyaw + 180;
3174 victim->stunned = 1;
3176 victim->Puff(abdomen);
3177 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
3183 if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3184 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3185 if (victim->id == 0) {
3188 emit_sound_at(landsound2, victim->coords);
3194 if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3195 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3196 if (victim->id == 0) {
3200 if (weaponactive != -1) {
3201 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3202 if (weapons[victim->weaponids[0]].getType() == staff) {
3203 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3205 if (weapons[weaponids[0]].getType() == staff) {
3206 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3209 emit_sound_at(swordstaffsound, victim->coords);
3211 emit_sound_at(metalhitsound, victim->coords);
3219 if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3220 if (weaponactive != -1) {
3223 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);
3225 weapons[weaponids[0]].thrown(aim * 50);
3228 weaponids[0] = weaponids[num_weapons];
3234 if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3236 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 && /*Animation::animations[victim->animTarget].height!=lowheight&&*/ victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
3238 if (!Tutorial::active) {
3239 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
3242 award_bonus(id, Slicebonus);
3243 if (!Tutorial::active) {
3244 emit_sound_at(knifeslicesound, victim->coords);
3246 //victim->jointVel(abdomen)+=relative*damagemult*200;
3247 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
3248 if (victim->id != 0 || difficulty == 2) {
3249 victim->frameTarget = 0;
3250 victim->animTarget = staggerbackhardanim;
3251 victim->targetyaw = targetyaw + 180;
3255 victim->lowreversaldelay = 0;
3256 victim->highreversaldelay = 0;
3257 if (aitype != playercontrolled) {
3258 weaponmissdelay = .6;
3261 if (!Tutorial::active) {
3262 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3263 weapons[weaponids[weaponactive]].bloody = 1;
3265 weapons[weaponids[weaponactive]].blooddrip += 3;
3268 XYZ footvel, footpoint;
3270 if (skeleton.free) {
3271 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3273 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3275 if (Tutorial::active) {
3276 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
3279 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
3281 footvel = DoRotation(facing, 0, 90, 0) * .8;
3282 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3283 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3284 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3285 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3287 victim->DoDamage(damagemult * 0);
3291 if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3292 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
3293 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
3294 award_bonus(id, Slashbonus);
3296 if (!Tutorial::active) {
3297 if (normaldotproduct(victim->facing, victim->coords - coords) < 0) {
3298 victim->DoBloodBig(2 / victim->armorhigh, 190);
3300 victim->DoBloodBig(2 / victim->armorhigh, 185);
3302 victim->deathbleeding = 1;
3303 emit_sound_at(swordslicesound, victim->coords);
3304 victim->frameTarget = 0;
3305 victim->animTarget = staggerbackhardanim;
3306 victim->targetyaw = targetyaw + 180;
3308 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3309 weapons[weaponids[weaponactive]].bloody = 1;
3311 weapons[weaponids[weaponactive]].blooddrip += 3;
3313 float bloodlossamount;
3314 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
3315 victim->bloodloss += bloodlossamount / victim->armorhigh;
3316 victim->DoDamage(damagemult * 0);
3318 XYZ footvel, footpoint;
3320 if (skeleton.free) {
3321 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3323 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3326 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3328 footvel = DoRotation(facing, 0, 90, 0) * .8;
3330 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3331 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3332 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3333 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3336 if (victim->weaponactive != -1) {
3337 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3338 if (weapons[victim->weaponids[0]].getType() == staff) {
3339 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3341 if (weapons[weaponids[0]].getType() == staff) {
3342 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3345 emit_sound_at(swordstaffsound, victim->coords);
3347 emit_sound_at(metalhitsound, victim->coords);
3352 victim->Puff(righthand);
3354 victim->frameTarget = 0;
3355 victim->animTarget = staggerbackhighanim;
3356 victim->targetyaw = targetyaw + 180;
3358 aim = DoRotation(facing, 0, 90, 0) * 21;
3360 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3361 victim->num_weapons--;
3362 if (victim->num_weapons) {
3363 victim->weaponids[0] = victim->weaponids[num_weapons];
3364 if (victim->weaponstuck == victim->num_weapons) {
3365 victim->weaponstuck = 0;
3368 victim->weaponactive = -1;
3369 for (unsigned i = 0; i < Person::players.size(); i++) {
3370 Person::players[i]->wentforweapon = 0;
3376 if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3377 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3378 if (!Tutorial::active) {
3379 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3384 if (Random() % 2 || creature == wolftype) {
3387 emit_sound_at(staffheadsound, victim->coords);
3391 relative = victim->coords - coords;
3393 Normalise(&relative);
3394 relative = DoRotation(relative, 0, 90, 0);
3396 Normalise(&relative);
3397 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3398 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3400 victim->jointVel(head) += relative * damagemult * 230;
3401 victim->jointVel(neck) += relative * damagemult * 230;
3403 if (!Tutorial::active) {
3404 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3406 award_bonus(id, solidhit, 30);
3411 if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3412 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3413 if (!Tutorial::active) {
3414 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3419 if (Random() % 2 || creature == wolftype) {
3422 emit_sound_at(staffheadsound, victim->coords);
3426 relative = victim->coords - coords;
3428 Normalise(&relative);
3429 relative = DoRotation(relative, 0, -90, 0);
3430 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3431 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3433 victim->jointVel(head) += relative * damagemult * 220;
3434 victim->jointVel(neck) += relative * damagemult * 220;
3436 if (!Tutorial::active) {
3437 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3439 award_bonus(id, solidhit, 60);
3444 if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3445 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3447 if (!Tutorial::active) {
3448 if (!victim->dead) {
3449 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3454 if (Random() % 2 || creature == wolftype) {
3457 emit_sound_at(staffbodysound, victim->coords);
3459 victim->skeleton.longdead = 0;
3460 victim->skeleton.free = 1;
3461 victim->skeleton.broken = 0;
3463 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3464 victim->skeleton.joints[i].velchange = 0;
3465 victim->skeleton.joints[i].locked = 0;
3466 //victim->skeleton.joints[i].velocity=0;
3473 Normalise(&relative);
3474 if (!victim->dead) {
3475 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3476 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3478 victim->jointVel(abdomen) += relative * damagemult * 40;
3481 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3482 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3485 victim->Puff(abdomen);
3486 if (!Tutorial::active) {
3487 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3489 if (!victim->dead) {
3490 award_bonus(id, solidhit, 40);
3496 if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3497 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3503 relative = victim->coords - coords;
3505 Normalise(&relative);
3509 if (Animation::animations[victim->animTarget].height == lowheight) {
3515 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3516 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3518 victim->jointVel(head) += relative * damagemult * 200;
3519 if (!Tutorial::active) {
3520 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3523 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3524 if (victim->howactive == typesleeping) {
3525 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3527 if (creature == wolftype) {
3528 emit_sound_at(clawslicesound, victim->coords, 128.);
3530 victim->DoBloodBig(2 / victim->armorhead, 175);
3533 if (victim->damage >= victim->damagetolerance) {
3536 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3537 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3539 victim->jointVel(abdomen) += relative * damagemult * 200;
3540 victim->frameTarget = 0;
3541 victim->animTarget = staggerbackhighanim;
3542 victim->targetyaw = targetyaw + 180;
3544 if (!Tutorial::active) {
3545 emit_sound_at(landsound2, victim->coords, 128.);
3547 victim->Puff(abdomen);
3548 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3549 if (creature == wolftype) {
3550 emit_sound_at(clawslicesound, victim->coords, 128.);
3552 victim->DoBloodBig(2 / victim->armorhigh, 170);
3558 if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3559 if ((victim->animTarget != jumpupanim) &&
3560 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3561 (victim != this->shared_from_this())) {
3566 if (!Tutorial::active) {
3567 emit_sound_at(landsound2, victim->coords, 128.);
3570 relative = victim->coords - coords;
3572 Normalise(&relative);
3574 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3577 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3578 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3580 relative = DoRotation(relative, 0, -90, 0);
3582 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3583 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) {
3584 victim->skeleton.joints[i].velocity = relative * 80;
3587 victim->Puff(rightankle);
3588 victim->Puff(leftankle);
3589 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3591 if (victim->damage >= victim->damagetolerance) {
3594 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3595 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3597 relative = DoRotation(relative, 0, -90, 0);
3598 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3599 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) {
3600 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3603 victim->jointVel(abdomen) += relative * damagemult * 200;
3604 victim->frameTarget = 0;
3605 victim->animTarget = staggerbackhighanim;
3606 victim->targetyaw = targetyaw + 180;
3608 if (!Tutorial::active) {
3609 emit_sound_at(landsound2, victim->coords, 128.);
3611 victim->Puff(abdomen);
3612 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3619 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3620 if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3629 if (!Tutorial::active) {
3630 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3632 if (creature == wolftype) {
3633 emit_sound_at(clawslicesound, victim->coords, 128);
3635 victim->DoBloodBig(2 / victim->armorhigh, 170);
3639 relative = victim->coords - oldcoords;
3641 Normalise(&relative);
3642 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3643 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3645 victim->jointVel(abdomen) += relative * damagemult * 200;
3646 victim->Puff(abdomen);
3647 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3649 award_bonus(id, Reversal);
3652 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3653 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3654 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3655 takeWeapon(victim->weaponids[victim->weaponactive]);
3656 victim->num_weapons--;
3657 if (victim->num_weapons > 0) {
3658 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3660 victim->weaponactive = -1;
3665 if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3674 emit_sound_at(whooshhitsound, victim->coords, 128.);
3677 relative = victim->coords - oldcoords;
3679 Normalise(&relative);
3680 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3681 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3683 victim->jointVel(abdomen) += relative * damagemult * 200;
3685 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3688 if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3698 award_bonus(id, staffreversebonus);
3700 if (!Tutorial::active) {
3701 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3704 award_bonus(id, staffreversebonus); // Huh, again?
3707 relative = victim->coords - oldcoords;
3709 Normalise(&relative);
3710 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3711 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3713 victim->jointVel(abdomen) += relative * damagemult * 200;
3715 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3718 if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3724 Normalise(&relative);
3726 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3727 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3729 victim->jointVel(lefthand) *= .1;
3730 victim->jointVel(leftwrist) *= .2;
3731 victim->jointVel(leftelbow) *= .5;
3732 victim->jointVel(leftshoulder) *= .7;
3733 victim->jointVel(righthand) *= .1;
3734 victim->jointVel(rightwrist) *= .2;
3735 victim->jointVel(rightelbow) *= .5;
3736 victim->jointVel(rightshoulder) *= .7;
3738 victim->Puff(abdomen);
3739 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3741 award_bonus(id, Reversal);
3745 if (weaponactive != -1 || creature == wolftype) {
3748 if (creature == rabbittype && weaponactive != -1) {
3749 if (weapons[weaponids[0]].getType() == staff) {
3754 if (weaponactive != -1) {
3755 victim->DoBloodBig(2 / victim->armorhigh, 225);
3756 emit_sound_at(knifeslicesound, victim->coords);
3757 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3758 weapons[weaponids[weaponactive]].bloody = 1;
3760 weapons[weaponids[weaponactive]].blooddrip += 3;
3762 if (weaponactive == -1 && creature == wolftype) {
3763 emit_sound_at(clawslicesound, victim->coords, 128.);
3765 victim->DoBloodBig(2 / victim->armorhigh, 175);
3770 if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3776 Normalise(&relative);
3778 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3779 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3781 victim->jointVel(lefthand) *= .1 - 1;
3782 victim->jointVel(leftwrist) *= .2 - 1;
3783 victim->jointVel(leftelbow) *= .5 - 1;
3784 victim->jointVel(leftshoulder) *= .7 - 1;
3785 victim->jointVel(righthand) *= .1 - 1;
3786 victim->jointVel(rightwrist) *= .2 - 1;
3787 victim->jointVel(rightelbow) *= .5 - 1;
3788 victim->jointVel(rightshoulder) *= .7 - 1;
3790 award_bonus(id, swordreversebonus);
3793 if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3802 if (!Tutorial::active) {
3803 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3807 relative = victim->coords - oldcoords;
3809 Normalise(&relative);
3810 relative = DoRotation(relative, 0, -90, 0);
3811 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3812 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3814 victim->jointVel(abdomen) += relative * damagemult * 200;
3815 victim->Puff(abdomen);
3816 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3818 award_bonus(id, Reversal);
3821 if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3824 victim->skeleton.spinny = 0;
3826 relative = facing * -1;
3828 Normalise(&relative);
3829 if (victim->id == 0) {
3832 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3833 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3835 victim->damage = victim->damagetolerance;
3836 victim->permanentdamage = victim->damagetolerance - 1;
3839 if (weaponactive != -1 || creature == wolftype) {
3842 if (creature == rabbittype && weaponactive != -1) {
3843 if (weapons[weaponids[0]].getType() == staff) {
3848 if (weaponactive != -1) {
3849 victim->DoBloodBig(200, 225);
3850 emit_sound_at(knifeslicesound, victim->coords);
3852 weapons[weaponids[weaponactive]].bloody = 2;
3854 weapons[weaponids[weaponactive]].blooddrip += 5;
3857 if (creature == wolftype && weaponactive == -1) {
3858 emit_sound_at(clawslicesound, victim->coords, 128.);
3860 victim->DoBloodBig(2, 175);
3863 award_bonus(id, spinecrusher);
3866 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3867 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3869 if (animTarget == knifefollowanim) {
3870 victim->DoBloodBig(200, 210);
3872 if (animTarget == knifesneakattackanim) {
3873 XYZ footvel, footpoint;
3875 footpoint = weapons[weaponids[0]].tippoint;
3877 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3879 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3880 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3881 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3882 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3883 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3884 victim->DoBloodBig(200, 195);
3885 award_bonus(id, tracheotomy);
3887 if (animTarget == knifefollowanim) {
3888 award_bonus(id, Stabbonus);
3889 XYZ footvel, footpoint;
3891 footpoint = weapons[weaponids[0]].tippoint;
3893 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3895 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3896 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3897 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3898 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3899 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3901 victim->bloodloss += 10000;
3902 victim->velocity = 0;
3903 emit_sound_at(fleshstabsound, victim->coords);
3905 weapons[weaponids[weaponactive]].bloody = 2;
3907 weapons[weaponids[weaponactive]].blooddrip += 5;
3911 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3913 victim->velocity = 0;
3914 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3915 victim->skeleton.joints[i].velocity = 0;
3917 if (animTarget == knifefollowanim) {
3919 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3920 victim->skeleton.joints[i].velocity = 0;
3923 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3924 emit_sound_at(fleshstabremovesound, victim->coords);
3926 weapons[weaponids[weaponactive]].bloody = 2;
3928 weapons[weaponids[weaponactive]].blooddrip += 5;
3930 XYZ footvel, footpoint;
3932 footpoint = weapons[weaponids[0]].tippoint;
3934 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3936 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3937 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3938 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3939 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3940 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3944 if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3945 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3946 award_bonus(id, backstab);
3950 XYZ footvel, footpoint;
3952 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3954 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3956 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3957 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3958 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3959 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3960 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3961 victim->DoBloodBig(200, 180);
3962 victim->DoBloodBig(200, 215);
3963 victim->bloodloss += 10000;
3964 victim->velocity = 0;
3965 emit_sound_at(fleshstabsound, victim->coords);
3967 weapons[weaponids[weaponactive]].bloody = 2;
3969 weapons[weaponids[weaponactive]].blooddrip += 5;
3973 if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3975 victim->velocity = 0;
3976 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3977 victim->skeleton.joints[i].velocity = 0;
3979 if (weaponactive != -1) {
3980 emit_sound_at(fleshstabremovesound, victim->coords);
3982 weapons[weaponids[weaponactive]].bloody = 2;
3984 weapons[weaponids[weaponactive]].blooddrip += 5;
3986 XYZ footvel, footpoint;
3988 footpoint = weapons[weaponids[0]].tippoint;
3990 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3992 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3993 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3994 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3995 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3996 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
4000 if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
4009 if (weaponactive == -1) {
4010 if (!Tutorial::active) {
4011 emit_sound_at(heavyimpactsound, victim->coords, 128.);
4016 if (weaponactive != -1 || creature == wolftype) {
4019 if (creature == rabbittype && weaponactive != -1) {
4020 if (weapons[weaponids[0]].getType() == staff) {
4025 if (weaponactive != -1) {
4026 victim->DoBloodBig(2 / victim->armorhead, 225);
4027 emit_sound_at(knifeslicesound, victim->coords);
4028 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
4029 weapons[weaponids[weaponactive]].bloody = 1;
4031 weapons[weaponids[weaponactive]].blooddrip += 3;
4033 if (weaponactive == -1 && creature == wolftype) {
4034 emit_sound_at(clawslicesound, victim->coords, 128.);
4036 victim->DoBloodBig(2 / victim->armorhead, 175);
4040 award_bonus(id, Reversal);
4045 relative = facing * -1;
4047 Normalise(&relative);
4048 relative = DoRotation(relative, 0, 90, 0);
4050 Normalise(&relative);
4051 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
4052 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
4054 victim->jointVel(head) += relative * damagemult * 200;
4055 if (victim->damage < victim->damagetolerance - 100) {
4056 victim->velocity = relative * 200;
4058 victim->DoDamage(damagemult * 100 / victim->protectionhead);
4059 victim->velocity = 0;
4062 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))) {
4066 relative = facing * -1;
4068 Normalise(&relative);
4069 relative = DoRotation(relative, 0, 90, 0);
4071 Normalise(&relative);
4072 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
4073 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
4075 victim->jointVel(head) += relative * damagemult * 200;
4078 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim)) {
4079 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
4080 award_bonus(id, reverseko);
4086 if (frameTarget > int(Animation::animations[animCurrent].frames.size()) - 1) {
4089 animTarget = getIdle();
4090 FootLand(leftfoot, 1);
4091 FootLand(rightfoot, 1);
4093 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
4094 animTarget = rollanim;
4096 emit_sound_at(movewhooshsound, coords, 128.);
4098 if (animCurrent == staggerbackhighanim) {
4099 animTarget = getIdle();
4101 if (animCurrent == staggerbackhardanim) {
4102 animTarget = getIdle();
4104 if (animCurrent == removeknifeanim) {
4105 animTarget = getIdle();
4107 if (animCurrent == crouchremoveknifeanim) {
4108 animTarget = getCrouch();
4110 if (animCurrent == backhandspringanim) {
4111 animTarget = getIdle();
4113 if (animCurrent == dodgebackanim) {
4114 animTarget = getIdle();
4116 if (animCurrent == drawleftanim) {
4117 animTarget = getIdle();
4119 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
4120 animTarget = getIdle();
4121 if (animCurrent == crouchdrawrightanim) {
4122 animTarget = getCrouch();
4124 if (weaponactive == -1) {
4126 } else if (weaponactive == 0) {
4128 if (num_weapons == 2) {
4130 buffer = weaponids[0];
4131 weaponids[0] = weaponids[1];
4132 weaponids[1] = buffer;
4136 if (weaponactive == -1) {
4137 emit_sound_at(knifesheathesound, coords, 128.);
4139 if (weaponactive != -1) {
4140 emit_sound_at(knifedrawsound, coords, 128.);
4143 if (animCurrent == rollanim) {
4144 animTarget = getCrouch();
4145 FootLand(leftfoot, 1);
4146 FootLand(rightfoot, 1);
4149 if (animTarget == walljumprightkickanim) {
4152 if (animTarget == walljumpleftkickanim) {
4155 animTarget = jumpdownanim;
4157 if (animCurrent == climbanim) {
4158 animTarget = getCrouch();
4160 coords += facing * .1;
4161 if (!isnormal(coords.x)) {
4172 if (animTarget == rabbitkickreversalanim) {
4173 animTarget = getCrouch();
4176 if (animTarget == jumpreversalanim) {
4177 animTarget = getCrouch();
4180 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
4181 if (attackkeydown && animTarget != walljumpfrontanim) {
4183 float closestdist = -1;
4185 if (Person::players.size() > 1) {
4186 for (unsigned i = 0; i < Person::players.size(); i++) {
4187 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4188 distance = distsq(&Person::players[i]->coords, &coords);
4189 if (closestdist == -1 || distance < closestdist) {
4190 closestdist = distance;
4196 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4197 victim = Person::players[closest];
4198 animTarget = walljumprightkickanim;
4200 XYZ rotatetarget = victim->coords - coords;
4201 Normalise(&rotatetarget);
4202 yaw = -asin(0 - rotatetarget.x);
4204 if (rotatetarget.z < 0) {
4207 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4208 velocity = (victim->coords - coords) * 4;
4213 if (animTarget == walljumpbackanim) {
4214 animTarget = backflipanim;
4216 velocity = facing * -8;
4219 resume_stream(whooshsound);
4222 if (animTarget == walljumprightanim) {
4223 animTarget = rightflipanim;
4227 velocity = DoRotation(facing, 0, 30, 0) * -8;
4230 if (animTarget == walljumpfrontanim) {
4231 animTarget = frontflipanim;
4235 velocity = facing * 8;
4239 resume_stream(whooshsound);
4242 if (animTarget == walljumpleftanim) {
4243 if (attackkeydown) {
4245 float closestdist = -1;
4247 if (Person::players.size() > 1) {
4248 for (unsigned i = 0; i < Person::players.size(); i++) {
4249 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4250 distance = distsq(&Person::players[i]->coords, &coords);
4251 if (closestdist == -1 || distance < closestdist) {
4252 closestdist = distance;
4258 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4259 victim = Person::players[closest];
4260 animTarget = walljumpleftkickanim;
4262 XYZ rotatetarget = victim->coords - coords;
4263 Normalise(&rotatetarget);
4264 yaw = -asin(0 - rotatetarget.x);
4266 if (rotatetarget.z < 0) {
4269 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4270 velocity = (victim->coords - coords) * 4;
4275 if (animTarget != walljumpleftkickanim) {
4276 animTarget = leftflipanim;
4280 velocity = DoRotation(facing, 0, -30, 0) * -8;
4284 resume_stream(whooshsound);
4287 if (animTarget == sneakattackanim) {
4288 animCurrent = getCrouch();
4289 animTarget = getCrouch();
4296 transspeed = 1000000;
4297 targetheadyaw += 180;
4298 coords -= facing * .7;
4300 coords.y = terrain.getHeight(coords.x, coords.z);
4305 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
4306 animTarget = getIdle();
4309 coords.y = terrain.getHeight(coords.x, coords.z);
4314 if (animCurrent == knifefollowanim) {
4315 animTarget = getIdle();
4318 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
4319 float ycoords = oldcoords.y;
4320 animTarget = getStop();
4325 transspeed = 1000000;
4326 targetheadyaw += 180;
4327 if (!isnormal(coords.x)) {
4330 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim) {
4331 oldcoords = coords + facing * .5;
4332 } else if (animCurrent == sweepreversalanim) {
4333 oldcoords = coords + facing * 1.1;
4334 } else if (animCurrent == upunchreversalanim) {
4335 oldcoords = coords + facing * 1.5;
4338 targetheadyaw += 180;
4341 } else if (animCurrent == knifeslashreversalanim) {
4342 oldcoords = coords + facing * .5;
4345 targetheadyaw += 90;
4348 } else if (animCurrent == staffspinhitreversalanim) {
4351 targetheadyaw += 180;
4356 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
4358 oldcoords.y = ycoords;
4360 currentoffset = coords - oldcoords;
4366 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4371 if (Animation::animations[animTarget].attack == reversed) {
4373 if (animTarget == sweepreversedanim) {
4376 animTarget = backhandspringanim;
4378 emit_sound_at(landsound, coords, 128);
4380 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4381 animTarget = rollanim;
4384 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4385 coords.y = oldcoords.y;
4387 if (animCurrent == knifeslashreversedanim) {
4388 animTarget = rollanim;
4393 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4394 coords.y = oldcoords.y;
4398 animTarget = jumpdownanim;
4401 animTarget = getIdle();
4403 if (wasLandhard()) {
4404 animTarget = getIdle();
4406 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4407 animTarget = getIdle();
4409 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4410 coords.y = oldcoords.y;
4411 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4412 targetoffset.y = coords.y;
4414 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4416 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4417 currentoffset.y -= (coords.y - targetoffset.y);
4418 coords.y = targetoffset.y;
4420 normalsupdatedelay = 0;
4422 if (animCurrent == upunchanim) {
4423 animTarget = getStop();
4424 normalsupdatedelay = 0;
4427 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4431 if (num_weapons > 0) {
4432 if (weapons[0].getType() == staff) {
4441 rabbitkickragdoll = 1;
4443 if (animCurrent == rabbitkickreversedanim) {
4449 skeleton.spinny = 0;
4450 SolidHitBonus(!id); // FIXME: tricky id
4454 animTarget = rollanim;
4457 pause_sound(whooshsound);
4462 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4466 skeleton.spinny = 0;
4468 if (animCurrent == jumpreversedanim) {
4474 skeleton.spinny = 0;
4475 SolidHitBonus(!id); // FIXME: tricky id
4479 animTarget = rollanim;
4480 coords += facing * 2;
4482 pause_sound(whooshsound);
4488 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) {
4489 animTarget = getupfromfrontanim;
4491 } else if (Animation::animations[animCurrent].attack == normalattack) {
4492 animTarget = getIdle();
4495 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4496 animTarget = blockhighleftstrikeanim;
4498 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4499 animTarget = getIdle();
4502 if (animCurrent == spinkickanim && victim->skeleton.free) {
4503 if (creature == rabbittype) {
4504 animTarget = fightidleanim;
4510 if (isIdle() && !wasIdle()) {
4511 normalsupdatedelay = 0;
4514 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4515 animTarget = jumpdownanim;
4518 if (!skeleton.free) {
4520 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4521 if (!isRun() || !wasRun()) {
4522 if (targetFrame().speed > currentFrame().speed) {
4523 target += multiplier * targetFrame().speed * speed * 2;
4525 if (targetFrame().speed <= currentFrame().speed) {
4526 target += multiplier * currentFrame().speed * speed * 2;
4529 if (isRun() && wasRun()) {
4531 tempspeed = velspeed;
4532 if (tempspeed < 10 * speedmult) {
4533 tempspeed = 10 * speedmult;
4535 /* FIXME - mixed of target and current here, is that intended? */
4536 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4538 } else if (transspeed) {
4539 target += multiplier * transspeed * speed * 2;
4541 if (!isRun() || !wasRun()) {
4542 if (targetFrame().speed > currentFrame().speed) {
4543 target += multiplier * targetFrame().speed * 2;
4545 if (targetFrame().speed <= currentFrame().speed) {
4546 target += multiplier * currentFrame().speed * 2;
4551 if (animCurrent != animTarget) {
4552 target = (target + oldtarget) / 2;
4556 frameCurrent = frameTarget;
4560 rot = targetrot * target;
4561 yaw += rot - oldrot;
4567 if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
4568 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4570 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4572 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4573 skeleton.joints[i].position = currentFrame().joints[i].position;
4576 skeleton.FindForwards();
4578 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4579 if (skeleton.muscles[i].visible) {
4580 skeleton.FindRotationMuscle(i, animTarget);
4583 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4584 if (skeleton.muscles[i].visible) {
4585 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4586 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4588 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4589 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4591 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4592 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4598 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4599 skeleton.joints[i].position = targetFrame().joints[i].position;
4602 skeleton.FindForwards();
4604 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4605 if (skeleton.muscles[i].visible) {
4606 skeleton.FindRotationMuscle(i, animTarget);
4609 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4610 if (skeleton.muscles[i].visible) {
4611 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4612 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4614 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4615 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4617 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4618 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4620 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) {
4621 skeleton.muscles[i].newrotate3 -= 360;
4623 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) {
4624 skeleton.muscles[i].newrotate3 += 360;
4626 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) {
4627 skeleton.muscles[i].newrotate2 -= 360;
4629 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) {
4630 skeleton.muscles[i].newrotate2 += 360;
4632 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) {
4633 skeleton.muscles[i].newrotate1 -= 360;
4635 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) {
4636 skeleton.muscles[i].newrotate1 += 360;
4642 oldanimCurrent = animCurrent;
4643 oldanimTarget = animTarget;
4644 oldframeTarget = frameTarget;
4645 oldframeCurrent = frameCurrent;
4647 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4648 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target - skeleton.joints[i].position) / multiplier;
4649 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target;
4651 offset = currentoffset * (1 - target) + targetoffset * target;
4652 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4653 if (skeleton.muscles[i].visible) {
4654 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * target;
4655 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * target;
4656 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * target;
4661 if (isLanding() && landhard) {
4665 animTarget = getLandhard();
4678 void Person::DoStuff()
4680 static XYZ terrainnormal;
4681 static XYZ flatfacing;
4682 static XYZ flatvelocity;
4683 static float flatvelspeed;
4684 static int bloodsize;
4685 static int startx, starty, endx, endy;
4686 static GLubyte color;
4687 static XYZ bloodvel;
4689 onfiredelay -= multiplier;
4690 if (onfiredelay < 0 && onfire) {
4691 if (Random() % 2 == 0) {
4697 crouchkeydowntime += multiplier;
4698 if (!crouchkeydown) {
4699 crouchkeydowntime = 0;
4701 jumpkeydowntime += multiplier;
4702 if (!jumpkeydown && skeleton.free) {
4703 jumpkeydowntime = 0;
4706 if (hostile || damage > 0 || bloodloss > 0) {
4710 if (isIdle() || isRun()) {
4714 if (num_weapons == 1 && weaponactive != -1) {
4719 blooddimamount -= multiplier * .3;
4721 speechdelay -= multiplier;
4722 texupdatedelay -= multiplier;
4723 interestdelay -= multiplier;
4724 flamedelay -= multiplier;
4725 parriedrecently -= multiplier;
4727 victim = this->shared_from_this();
4732 speed = 1.1 * speedmult;
4734 speed = 1.0 * speedmult;
4736 if (!skeleton.free) {
4737 rabbitkickragdoll = 0;
4742 if (id != 0 && (creature == rabbittype || difficulty != 2)) {
4745 if (id != 0 && creature == wolftype && difficulty == 2) {
4747 if (aitype != passivetype) {
4749 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) {
4756 if (animTarget == wolfrunninganim && !superruntoggle) {
4757 animTarget = getRun();
4761 if (weaponactive == -1 && num_weapons > 0) {
4762 if (weapons[weaponids[0]].getType() == staff) {
4768 burnt += multiplier;
4773 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4775 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4782 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
4783 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4787 while (flamedelay < 0 && onfire) {
4789 int howmany = fabs(Random() % (skeleton.joints.size()));
4790 if (skeleton.free) {
4791 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4792 flatfacing = skeleton.joints[howmany].position * scale + coords;
4794 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4795 flatvelocity = (coords - oldcoords) / multiplier / 2;
4797 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4800 while (flamedelay < 0 && !onfire && Tutorial::active && id != 0) {
4802 int howmany = fabs(Random() % (skeleton.joints.size()));
4803 if (skeleton.free) {
4804 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4805 flatfacing = skeleton.joints[howmany].position * scale + coords;
4807 flatvelocity = (coords - oldcoords) / multiplier / 2;
4808 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4810 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4814 bleeding -= multiplier * .3;
4815 if (bloodtoggle == 2) {
4816 skeleton.drawmodel.textureptr.bind();
4817 if ((bleeding <= 0) && (detail != 2)) {
4823 if (neckspurtamount > 0) {
4824 neckspurtamount -= multiplier;
4825 neckspurtdelay -= multiplier * 3;
4826 neckspurtparticledelay -= multiplier * 3;
4827 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4830 if (skeleton.free) {
4831 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4832 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4833 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4835 bloodvel.z = 5 * neckspurtamount;
4836 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4837 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4838 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4840 neckspurtparticledelay = .05;
4842 if (neckspurtdelay < 0) {
4847 if (deathbleeding > 0 && dead != 2) {
4848 if (deathbleeding < 5) {
4849 bleeddelay -= deathbleeding * multiplier / 4;
4851 bleeddelay -= 5 * multiplier / 4;
4853 if (bleeddelay < 0 && bloodtoggle) {
4858 if (skeleton.free) {
4859 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4860 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4862 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4863 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4867 bloodloss += deathbleeding * multiplier * 80;
4868 deathbleeding -= multiplier * 1.6;
4869 if (deathbleeding < 0) {
4872 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4873 if (weaponactive != -1) {
4874 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4875 weapons[weaponids[0]].velocity.x += .01;
4878 weaponids[0] = weaponids[num_weapons];
4879 if (weaponstuck == num_weapons) {
4884 for (unsigned i = 0; i < Person::players.size(); i++) {
4885 Person::players[i]->wentforweapon = 0;
4893 if (!dead && creature == wolftype) {
4894 award_bonus(0, Wolfbonus);
4897 if (animTarget == knifefollowedanim && !skeleton.free) {
4898 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4899 skeleton.joints[i].velocity = 0;
4900 skeleton.joints[i].velocity.y = -2;
4903 if (id != 0 && unconscioustime > .1) {
4911 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4912 texupdatedelay = .12;
4914 bloodsize = 5 - realtexdetail;
4918 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4919 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4920 endx = startx + bloodsize;
4921 endy = starty + bloodsize;
4931 if (endx > skeleton.skinsize - 1) {
4932 endx = skeleton.skinsize - 1;
4935 if (endy > skeleton.skinsize - 1) {
4936 endy = skeleton.skinsize - 1;
4939 if (endx < startx) {
4942 if (endy < starty) {
4946 for (int i = startx; i < endx; i++) {
4947 for (int j = starty; j < endy; j++) {
4948 if (Random() % 2 == 0) {
4949 color = Random() % 85 + 170;
4950 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2) {
4951 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4953 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4954 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4959 skeleton.drawmodel.textureptr.bind();
4963 if (skeleton.free) {
4964 bleedx += 4 * direction / realtexdetail;
4966 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4968 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4971 bleedy -= 4 / realtexdetail;
4973 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4975 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4980 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4981 righthandmorphness = targetrighthandmorphness;
4982 righthandmorphstart = righthandmorphend;
4983 } else if (righthandmorphness > targetrighthandmorphness) {
4984 righthandmorphness -= multiplier * 4;
4985 } else if (righthandmorphness < targetrighthandmorphness) {
4986 righthandmorphness += multiplier * 4;
4989 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4990 lefthandmorphness = targetlefthandmorphness;
4991 lefthandmorphstart = lefthandmorphend;
4992 } else if (lefthandmorphness > targetlefthandmorphness) {
4993 lefthandmorphness -= multiplier * 4;
4994 } else if (lefthandmorphness < targetlefthandmorphness) {
4995 lefthandmorphness += multiplier * 4;
4998 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4999 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
5000 tailmorphness = targettailmorphness;
5001 tailmorphstart = tailmorphend;
5002 } else if (tailmorphness > targettailmorphness) {
5003 tailmorphness -= multiplier * 10;
5004 } else if (tailmorphness < targettailmorphness) {
5005 tailmorphness += multiplier * 10;
5009 if (creature == wolftype) {
5010 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
5011 tailmorphness = targettailmorphness;
5012 tailmorphstart = tailmorphend;
5013 } else if (tailmorphness > targettailmorphness) {
5014 tailmorphness -= multiplier * 2;
5015 } else if (tailmorphness < targettailmorphness) {
5016 tailmorphness += multiplier * 2;
5020 if (headmorphend == 3 || headmorphstart == 3) {
5021 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
5022 headmorphness = targetheadmorphness;
5023 headmorphstart = headmorphend;
5024 } else if (headmorphness > targetheadmorphness) {
5025 headmorphness -= multiplier * 7;
5026 } else if (headmorphness < targetheadmorphness) {
5027 headmorphness += multiplier * 7;
5029 } else if (headmorphend == 5 || headmorphstart == 5) {
5030 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
5031 headmorphness = targetheadmorphness;
5032 headmorphstart = headmorphend;
5033 } else if (headmorphness > targetheadmorphness) {
5034 headmorphness -= multiplier * 10;
5035 } else if (headmorphness < targetheadmorphness) {
5036 headmorphness += multiplier * 10;
5039 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
5040 headmorphness = targetheadmorphness;
5041 headmorphstart = headmorphend;
5042 } else if (headmorphness > targetheadmorphness) {
5043 headmorphness -= multiplier * 4;
5044 } else if (headmorphness < targetheadmorphness) {
5045 headmorphness += multiplier * 4;
5049 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
5050 chestmorphness = targetchestmorphness;
5051 chestmorphstart = chestmorphend;
5052 } else if (chestmorphness > targetchestmorphness) {
5053 chestmorphness -= multiplier;
5054 } else if (chestmorphness < targetchestmorphness) {
5055 chestmorphness += multiplier;
5058 if (dead != 2 && howactive <= typesleeping) {
5059 if (chestmorphstart == 0 && chestmorphend == 0) {
5061 targetchestmorphness = 1;
5064 if (chestmorphstart != 0 && chestmorphend != 0) {
5066 targetchestmorphness = 1;
5068 if (environment == snowyenvironment) {
5071 if (skeleton.free) {
5072 footvel = skeleton.specialforward[0] * -1;
5073 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
5075 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
5076 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
5078 if (animTarget == sleepanim) {
5079 footvel = DoRotation(footvel, 0, 90, 0);
5081 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
5085 if (!dead && howactive < typesleeping) {
5086 blinkdelay -= multiplier * 2;
5087 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
5089 targetheadmorphness = 1;
5091 blinkdelay = (float)(abs(Random() % 40)) / 5;
5093 if (headmorphstart == 3 && headmorphend == 3) {
5095 targetheadmorphness = 1;
5100 twitchdelay -= multiplier * 1.5;
5101 if (animTarget != hurtidleanim) {
5102 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
5104 targetheadmorphness = 1;
5106 twitchdelay = (float)(abs(Random() % 40)) / 5;
5108 if (headmorphstart == 5 && headmorphend == 5) {
5110 targetheadmorphness = 1;
5114 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
5115 twitchdelay3 -= multiplier * 1;
5116 if (Random() % 2 == 0) {
5117 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
5118 righthandmorphness = 0;
5119 targetrighthandmorphness = 1;
5120 righthandmorphend = 1;
5121 if (Random() % 2 == 0) {
5122 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
5125 if (righthandmorphstart == 1 && righthandmorphend == 1) {
5126 righthandmorphness = 0;
5127 targetrighthandmorphness = 1;
5128 righthandmorphend = 0;
5131 if (Random() % 2 == 0) {
5132 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
5133 lefthandmorphness = 0;
5134 targetlefthandmorphness = 1;
5135 lefthandmorphend = 1;
5136 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
5138 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
5139 lefthandmorphness = 0;
5140 targetlefthandmorphness = 1;
5141 lefthandmorphend = 0;
5147 if (creature == rabbittype) {
5148 if (howactive < typesleeping) {
5149 twitchdelay2 -= multiplier * 1.5;
5151 twitchdelay2 -= multiplier * 0.5;
5153 if (howactive <= typesleeping) {
5154 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
5156 targettailmorphness = 1;
5158 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
5160 if (tailmorphstart == 1 && tailmorphend == 1) {
5162 targettailmorphness = 1;
5165 if (tailmorphstart == 2 && tailmorphend == 2) {
5167 targettailmorphness = 1;
5174 if (creature == wolftype) {
5175 twitchdelay2 -= multiplier * 1.5;
5176 if (tailmorphend != 0) {
5177 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
5179 targettailmorphness = 1;
5184 if (tailmorphend != 5) {
5185 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
5187 targettailmorphness = 1;
5192 if (twitchdelay2 <= 0) {
5193 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
5195 targettailmorphness = 1;
5198 if (tailmorphstart == 1 && tailmorphend == 1) {
5200 targettailmorphness = 1;
5203 if (tailmorphstart == 2 && tailmorphend == 2) {
5205 targettailmorphness = 1;
5208 if (tailmorphstart == 3 && tailmorphend == 3) {
5210 targettailmorphness = 1;
5213 if (tailmorphstart == 4 && tailmorphend == 4) {
5215 targettailmorphness = 1;
5222 unconscioustime = 0;
5225 if (dead == 1 || howactive == typesleeping) {
5226 unconscioustime += multiplier;
5227 //If unconscious, close eyes and mouth
5228 if (righthandmorphend != 0) {
5229 righthandmorphness = 0;
5231 righthandmorphend = 0;
5232 targetrighthandmorphness = 1;
5234 if (lefthandmorphend != 0) {
5235 lefthandmorphness = 0;
5237 lefthandmorphend = 0;
5238 targetlefthandmorphness = 1;
5240 if (headmorphend != 3 && headmorphend != 5) {
5244 targetheadmorphness = 1;
5247 if (howactive > typesleeping) {
5250 if (bloodtoggle && !bled) {
5251 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5252 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5253 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5254 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5258 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5264 if (dead == 2 || howactive > typesleeping) {
5265 //If dead, open mouth and hands
5266 if (righthandmorphend != 0) {
5267 righthandmorphness = 0;
5269 righthandmorphend = 0;
5270 targetrighthandmorphness = 1;
5272 if (lefthandmorphend != 0) {
5273 lefthandmorphness = 0;
5275 lefthandmorphend = 0;
5276 targetlefthandmorphness = 1;
5278 if (headmorphend != 2) {
5282 targetheadmorphness = 1;
5285 if (stunned > 0 && !dead && headmorphend != 2) {
5286 if (headmorphend != 4) {
5290 targetheadmorphness = 1;
5293 if (damage > damagetolerance && !dead) {
5296 unconscioustime = 0;
5298 if (creature == wolftype) {
5299 award_bonus(0, Wolfbonus);
5304 if (weaponactive != -1) {
5305 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5306 weapons[weaponids[0]].velocity.x += .01;
5309 weaponids[0] = weaponids[num_weapons];
5310 if (weaponstuck == num_weapons) {
5315 for (unsigned i = 0; i < Person::players.size(); i++) {
5316 Person::players[i]->wentforweapon = 0;
5320 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
5329 damage -= multiplier * 13;
5330 permanentdamage -= multiplier * 4;
5331 if (isIdle() || isCrouch()) {
5332 permanentdamage -= multiplier * 4;
5338 if (permanentdamage < 0) {
5339 permanentdamage = 0;
5341 if (superpermanentdamage < 0) {
5342 superpermanentdamage = 0;
5344 if (permanentdamage < superpermanentdamage) {
5345 permanentdamage = superpermanentdamage;
5347 if (damage < permanentdamage) {
5348 damage = permanentdamage;
5350 if (dead == 1 && damage < damagetolerance) {
5354 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5355 skeleton.joints[i].velocity = 0;
5358 if (permanentdamage > damagetolerance && dead != 2) {
5361 if (weaponactive != -1) {
5362 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5363 weapons[weaponids[0]].velocity.x += .01;
5366 weaponids[0] = weaponids[num_weapons];
5367 if (weaponstuck == num_weapons) {
5372 for (unsigned i = 0; i < Person::players.size(); i++) {
5373 Person::players[i]->wentforweapon = 0;
5379 if (!dead && creature == wolftype) {
5380 award_bonus(0, Wolfbonus);
5383 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance) {
5384 award_bonus(id, touchofdeath);
5386 if (id != 0 && unconscioustime > .1) {
5394 emit_sound_at(breaksound, coords);
5397 if (skeleton.free == 1) {
5399 pause_sound(whooshsound);
5403 //If knocked over, open hands and close mouth
5404 if (righthandmorphend != 0) {
5405 righthandmorphness = 0;
5407 righthandmorphend = 0;
5408 targetrighthandmorphness = 1;
5410 if (lefthandmorphend != 0) {
5411 lefthandmorphness = 0;
5413 lefthandmorphend = 0;
5414 targetlefthandmorphness = 1;
5416 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
5417 if (headmorphend != 0) {
5421 targetheadmorphness = 1;
5425 skeleton.DoGravity(&scale);
5427 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
5428 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1)) {
5429 award_bonus(id, deepimpact);
5431 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5435 if (!skeleton.joints.empty()) {
5436 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5437 average += skeleton.joints[j].position;
5439 average /= skeleton.joints.size();
5440 coords += average * scale;
5441 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5442 skeleton.joints[j].position -= average;
5444 average /= multiplier;
5448 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5449 velocity += skeleton.joints[i].velocity * scale;
5451 velocity /= skeleton.joints.size();
5453 if (!isnormal(velocity.x) && velocity.x) {
5457 if (findLength(&average) < 10 && dead && skeleton.free) {
5458 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5459 if (skeleton.longdead > 2000) {
5460 if (skeleton.longdead > 6000) {
5462 pause_sound(whooshsound);
5468 if (dead == 2 && bloodloss < damagetolerance) {
5470 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5472 if (bloodtoggle && !bled) {
5473 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5474 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5475 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5476 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5477 float size = .2 * 1.2;
5480 Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5485 if (dead == 2 && bloodloss >= damagetolerance) {
5487 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5488 if (bleeding <= 0) {
5491 if (bloodtoggle && !bled) {
5492 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5493 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5494 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5495 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5499 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5507 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5508 bool canrecover = 1;
5509 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5510 startpoint = coords;
5513 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1) {
5516 if (velocity.y < -30) {
5519 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5520 if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) {
5521 colviewer = startpoint;
5522 coltarget = endpoint;
5523 if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1) {
5533 terrainnormal = jointPos(groin) - jointPos(abdomen);
5534 if (joint(groin).locked && joint(abdomen).locked) {
5535 terrainnormal = jointPos(groin) - jointPos(abdomen);
5536 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5538 if (joint(abdomen).locked && joint(neck).locked) {
5539 terrainnormal = jointPos(abdomen) - jointPos(neck);
5540 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5542 if (joint(groin).locked && joint(neck).locked) {
5543 terrainnormal = jointPos(groin) - jointPos(neck);
5544 middle = (jointPos(groin) + jointPos(neck)) / 2;
5546 Normalise(&terrainnormal);
5548 targetyaw = -asin(0 - terrainnormal.x);
5549 targetyaw *= 360 / 6.28;
5550 if (terrainnormal.z < 0) {
5551 targetyaw = 180 - targetyaw;
5556 animTarget = flipanim;
5557 crouchtogglekeydown = 1;
5562 animCurrent = tempanim;
5566 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5567 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5568 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5573 if (findLength(&average) < 10 && !dead && skeleton.free) {
5574 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5575 if (skeleton.longdead > (damage + 500) * 1.5) {
5577 pause_sound(whooshsound);
5584 terrainnormal = jointPos(groin) - jointPos(abdomen);
5585 if (joint(groin).locked && joint(abdomen).locked) {
5586 terrainnormal = jointPos(groin) - jointPos(abdomen);
5587 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5589 if (joint(abdomen).locked && joint(neck).locked) {
5590 terrainnormal = jointPos(abdomen) - jointPos(neck);
5591 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5593 if (joint(groin).locked && joint(neck).locked) {
5594 terrainnormal = jointPos(groin) - jointPos(neck);
5595 middle = (jointPos(groin) + jointPos(neck)) / 2;
5597 Normalise(&terrainnormal);
5599 targetyaw = -asin(0 - terrainnormal.x);
5600 targetyaw *= 360 / 6.28;
5601 if (terrainnormal.z < 0) {
5602 targetyaw = 180 - targetyaw;
5606 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5608 if (skeleton.forward.y < 0) {
5609 animTarget = getupfrombackanim;
5613 if (skeleton.forward.y > -.3) {
5614 animTarget = getupfromfrontanim;
5622 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5623 animTarget = rollanim;
5624 targetyaw = lookyaw;
5628 if (forwardkeydown) {
5637 if (forwardkeydown) {
5645 if (!leftkeydown && !rightkeydown) {
5653 if (abs(targettilt2) > 50) {
5656 animCurrent = tempanim;
5659 tilt2 = targettilt2;
5661 if (middle.y > 0 && animTarget != rollanim) {
5662 targetoffset.y = middle.y + 1;
5665 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5666 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5667 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5674 if (num_weapons > 0) {
5675 if (weapons[0].getType() == staff) {
5679 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5680 if (velocity.y > -30) {
5682 tempvelocity = velocity;
5683 Normalise(&tempvelocity);
5684 targetyaw = -asin(0 - tempvelocity.x);
5685 targetyaw *= 360 / 6.28;
5686 if (velocity.z < 0) {
5687 targetyaw = 180 - targetyaw;
5692 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5693 animTarget = rollanim;
5696 animTarget = backhandspringanim;
5702 emit_sound_at(movewhooshsound, coords, 128.);
5704 animCurrent = animTarget;
5705 frameCurrent = frameTarget - 1;
5717 if (skeleton.freefall == 0) {
5722 if (aitype != passivetype || skeleton.free == 1) {
5723 if (findLengthfast(&velocity) > .1) {
5724 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5725 if (Object::objects[i]->type == firetype) {
5726 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) {
5728 if (!Object::objects[i]->onfire) {
5729 emit_sound_at(firestartsound, Object::objects[i]->position);
5731 Object::objects[i]->onfire = 1;
5734 if (Object::objects[i]->onfire) {
5740 if (Object::objects[i]->type == bushtype) {
5741 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) {
5743 if (!Object::objects[i]->onfire) {
5744 emit_sound_at(firestartsound, Object::objects[i]->position);
5746 Object::objects[i]->onfire = 1;
5750 if (Object::objects[i]->onfire) {
5754 if (Object::objects[i]->messedwith <= 0) {
5758 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5761 addEnvSound(coords, 4 * findLength(&velocity));
5765 if (environment == grassyenvironment) {
5766 howmany = findLength(&velocity) * 4;
5768 if (environment == snowyenvironment) {
5769 howmany = findLength(&velocity) * 2;
5772 if (environment != desertenvironment) {
5773 for (int j = 0; j < howmany; j++) {
5774 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5775 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5776 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5779 pos.x += float(abs(Random() % 100) - 50) / 200;
5780 pos.y += float(abs(Random() % 100) - 50) / 200;
5781 pos.z += float(abs(Random() % 100) - 50) / 200;
5782 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);
5783 Sprite::setLastSpriteSpecial(1);
5787 howmany = findLength(&velocity) * 4;
5789 if (environment == snowyenvironment) {
5790 for (int j = 0; j < howmany; j++) {
5791 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5792 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5793 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5796 pos.x += float(abs(Random() % 100) - 50) / 200;
5797 pos.y += float(abs(Random() % 100) - 50) / 200;
5798 pos.z += float(abs(Random() % 100) - 50) / 200;
5799 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5800 Sprite::setLastSpriteSpecial(2);
5805 Object::objects[i]->rotx += velocity.x * multiplier * 6;
5806 Object::objects[i]->roty += velocity.z * multiplier * 6;
5807 Object::objects[i]->messedwith = .5;
5811 if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) {
5812 if (Object::objects[i]->pitch == 0) {
5815 tempcoord = coords - Object::objects[i]->position;
5816 tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0);
5817 tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0);
5818 tempcoord += Object::objects[i]->position;
5820 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) {
5821 if (Object::objects[i]->messedwith <= 0) {
5825 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5828 addEnvSound(coords, 4 * findLength(&velocity));
5832 if (environment == grassyenvironment) {
5833 howmany = findLength(&velocity) * 4;
5835 if (environment == snowyenvironment) {
5836 howmany = findLength(&velocity) * 2;
5839 if (environment != desertenvironment) {
5840 for (int j = 0; j < howmany; j++) {
5841 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5842 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5843 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5845 pos += velocity * .1;
5847 pos.x += float(abs(Random() % 100) - 50) / 150;
5848 pos.y += float(abs(Random() % 100) - 50) / 150;
5849 pos.z += float(abs(Random() % 100) - 50) / 150;
5850 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);
5851 Sprite::setLastSpriteSpecial(1);
5855 howmany = findLength(&velocity) * 4;
5857 if (environment == snowyenvironment) {
5858 for (int j = 0; j < howmany; j++) {
5859 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5860 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5861 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5863 pos += velocity * .1;
5865 pos.x += float(abs(Random() % 100) - 50) / 150;
5866 pos.y += float(abs(Random() % 100) - 50) / 150;
5867 pos.z += float(abs(Random() % 100) - 50) / 150;
5868 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5869 Sprite::setLastSpriteSpecial(2);
5874 Object::objects[i]->messedwith = .5;
5881 if (!skeleton.free) {
5884 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype) {
5888 if (aitype != passivetype && victim->skeleton.free && !victim->dead) {
5892 if (Tutorial::active && id != 0) {
5895 if (play && aitype != playercontrolled) {
5896 int whichsound = -1;
5897 if (speechdelay <= 0) {
5898 unsigned int i = abs(Random() % 4);
5900 whichsound = PersonType::types[creature].soundsTalk[i];
5905 if (whichsound != -1) {
5906 emit_sound_at(whichsound, coords);
5910 if (animTarget == staggerbackhighanim) {
5913 if (animTarget == staggerbackhardanim) {
5916 staggerdelay -= multiplier;
5917 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
5920 if (velocity.y < -30 && animTarget == jumpdownanim) {
5923 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5924 animTarget = getIdle();
5928 weaponmissdelay -= multiplier;
5929 highreversaldelay -= multiplier;
5930 lowreversaldelay -= multiplier;
5931 lastcollide -= multiplier;
5932 skiddelay -= multiplier;
5933 if (!isnormal(velocity.x) && velocity.x) {
5936 if (!isnormal(targettilt) && targettilt) {
5939 if (!isnormal(targettilt2) && targettilt2) {
5942 if (!isnormal(targetyaw) && targetyaw) {
5946 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5947 //open hands and close mouth
5948 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5949 righthandmorphness = 0;
5950 righthandmorphend = 0;
5951 targetrighthandmorphness = 1;
5954 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5955 lefthandmorphness = 0;
5956 lefthandmorphend = 0;
5957 targetlefthandmorphness = 1;
5960 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5963 targetheadmorphness = 1;
5967 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) {
5968 //open hands and mouth
5969 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5970 righthandmorphness = 0;
5971 righthandmorphend = 0;
5972 targetrighthandmorphness = 1;
5975 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5976 lefthandmorphness = 0;
5977 lefthandmorphend = 0;
5978 targetlefthandmorphness = 1;
5981 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5984 targetheadmorphness = 1;
5988 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5989 //close hands and mouth
5990 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5991 righthandmorphness = 0;
5992 righthandmorphend = 1;
5993 targetrighthandmorphness = 1;
5996 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5997 lefthandmorphness = 0;
5998 lefthandmorphend = 1;
5999 targetlefthandmorphness = 1;
6002 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
6005 targetheadmorphness = 1;
6009 if (animTarget == spinkickanim ||
6010 animTarget == staffspinhitreversalanim ||
6011 animTarget == staffspinhitreversedanim ||
6012 animTarget == staffhitreversalanim ||
6013 animTarget == staffhitreversedanim ||
6014 animTarget == hurtidleanim ||
6015 animTarget == winduppunchanim ||
6016 animTarget == swordslashreversalanim ||
6017 animTarget == swordslashreversedanim ||
6018 animTarget == knifeslashreversalanim ||
6019 animTarget == knifeslashreversedanim ||
6020 animTarget == knifethrowanim ||
6021 animTarget == knifefollowanim ||
6022 animTarget == knifefollowedanim ||
6023 animTarget == killanim ||
6024 animTarget == dropkickanim ||
6025 animTarget == upunchanim ||
6026 animTarget == knifeslashstartanim ||
6027 animTarget == swordslashanim ||
6028 animTarget == staffhitanim ||
6029 animTarget == staffspinhitanim ||
6030 animTarget == staffgroundsmashanim ||
6031 animTarget == spinkickreversalanim ||
6032 animTarget == sweepreversalanim ||
6033 animTarget == lowkickanim ||
6034 animTarget == sweepreversedanim ||
6035 animTarget == rabbitkickreversalanim ||
6036 animTarget == rabbitkickreversedanim ||
6037 animTarget == jumpreversalanim ||
6038 animTarget == jumpreversedanim) {
6039 //close hands and yell
6040 if (righthandmorphend != 1 &&
6041 righthandmorphness == targetrighthandmorphness) {
6042 righthandmorphness = 0;
6043 righthandmorphend = 1;
6044 targetrighthandmorphness = 1;
6047 if (lefthandmorphend != 1 &&
6048 lefthandmorphness == targetlefthandmorphness) {
6049 lefthandmorphness = 0;
6050 lefthandmorphend = 1;
6051 targetlefthandmorphness = 1;
6054 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
6057 targetheadmorphness = 1;
6064 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
6065 (victim->aitype != searchtype) && (aitype != passivetype) &&
6066 (aitype != searchtype) && (victim->id < Person::players.size())) {
6067 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
6071 if (!dead && animTarget != hurtidleanim) {
6072 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
6073 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
6076 targetheadmorphness = 1;
6081 if (weaponactive != -1) {
6082 if (weapons[weaponids[weaponactive]].getType() != staff) {
6083 righthandmorphstart = 1;
6084 righthandmorphend = 1;
6086 if (weapons[weaponids[weaponactive]].getType() == staff) {
6087 righthandmorphstart = 2;
6088 righthandmorphend = 2;
6090 targetrighthandmorphness = 1;
6093 terrainnormal = terrain.getNormal(coords.x, coords.z);
6095 if (Animation::animations[animTarget].attack != reversal) {
6096 if (!isnormal(coords.x)) {
6105 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
6106 facing = flatfacing;
6107 ReflectVector(&facing, terrainnormal);
6111 animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
6113 targettilt2 = -facing.y * 20;
6119 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim) {
6122 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6123 flatvelocity = velocity;
6125 flatvelspeed = findLength(&flatvelocity);
6126 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
6127 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
6128 if (velocity.y < 0) {
6131 if (velocity.y < 0) {
6134 if (targettilt > 25) {
6137 if (targettilt < -25) {
6142 if (targettilt2 > 45) {
6145 if (targettilt2 < -45) {
6148 if (abs(tilt2 - targettilt2) < multiplier * 400) {
6149 tilt2 = targettilt2;
6150 } else if (tilt2 > targettilt2) {
6151 tilt2 -= multiplier * 400;
6152 } else if (tilt2 < targettilt2) {
6153 tilt2 += multiplier * 400;
6155 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
6164 if (!isnormal(targettilt) && targettilt) {
6167 if (!isnormal(targettilt2) && targettilt2) {
6172 if (animTarget == rabbittackleanim) {
6173 velocity += facing * multiplier * speed * 700 * scale;
6174 velspeed = findLength(&velocity);
6175 if (velspeed > speed * 65 * scale) {
6176 velocity /= velspeed;
6177 velspeed = speed * 65 * scale;
6178 velocity *= velspeed;
6180 velocity.y += gravity * multiplier * 20;
6181 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6182 velspeed = findLength(&velocity);
6183 velocity = flatfacing * velspeed;
6185 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
6186 if (isRun() || animTarget == rabbitkickanim) {
6187 velocity += facing * multiplier * speed * 700 * scale;
6188 velspeed = findLength(&velocity);
6189 if (velspeed > speed * 45 * scale) {
6190 velocity /= velspeed;
6191 velspeed = speed * 45 * scale;
6192 velocity *= velspeed;
6194 velocity.y += gravity * multiplier * 20;
6195 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6196 velspeed = findLength(&velocity);
6197 if (velspeed < speed * 30 * scale) {
6198 velspeed = speed * 30 * scale;
6200 velocity = flatfacing * velspeed;
6202 } else if (isRun()) {
6203 velocity += facing * multiplier * speed * 700 * scale;
6204 velspeed = findLength(&velocity);
6205 if (creature == rabbittype) {
6206 if (velspeed > speed * 55 * scale) {
6207 velocity /= velspeed;
6208 velspeed = speed * 55 * scale;
6209 velocity *= velspeed;
6212 if (creature == wolftype) {
6213 if (velspeed > speed * 75 * scale) {
6214 velocity /= velspeed;
6215 velspeed = speed * 75 * scale;
6216 velocity *= velspeed;
6219 velocity.y += gravity * multiplier * 20;
6220 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6221 velspeed = findLength(&velocity);
6222 velocity = flatfacing * velspeed;
6225 if (animTarget == rollanim && targetFrame().label != 6) {
6226 velocity += facing * multiplier * speed * 700 * scale;
6227 velspeed = findLength(&velocity);
6228 if (velspeed > speed * 45 * scale) {
6229 velocity /= velspeed;
6230 velspeed = speed * 45 * scale;
6231 velocity *= velspeed;
6233 velocity.y += gravity * multiplier * 20;
6234 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6235 velspeed = findLength(&velocity);
6236 velocity = flatfacing * velspeed;
6239 if (animTarget == sneakanim || animTarget == walkanim) {
6240 velocity += facing * multiplier * speed * 700 * scale;
6241 velspeed = findLength(&velocity);
6242 if (velspeed > speed * 12 * scale) {
6243 velocity /= velspeed;
6244 velspeed = speed * 12 * scale;
6245 velocity *= velspeed;
6247 velocity.y += gravity * multiplier * 20;
6248 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6249 velspeed = findLength(&velocity);
6250 velocity = flatfacing * velspeed;
6253 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
6254 velocity += facing * multiplier * speed * 700 * scale;
6255 velspeed = findLength(&velocity);
6256 if (velspeed > speed * 2 * scale) {
6257 velocity /= velspeed;
6258 velspeed = speed * 2 * scale;
6259 velocity *= velspeed;
6261 velocity.y += gravity * multiplier * 20;
6262 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6263 velspeed = findLength(&velocity);
6264 velocity = flatfacing * velspeed;
6267 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
6268 velocity -= facing * multiplier * speed * 700 * scale;
6269 velspeed = findLength(&velocity);
6270 if (velspeed > speed * 2 * scale) {
6271 velocity /= velspeed;
6272 velspeed = speed * 2 * scale;
6273 velocity *= velspeed;
6275 velocity.y += gravity * multiplier * 20;
6276 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6277 velspeed = findLength(&velocity);
6278 velocity = flatfacing * velspeed * -1;
6281 if (animTarget == fightsidestep) {
6282 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
6283 velspeed = findLength(&velocity);
6284 if (velspeed > speed * 12 * scale) {
6285 velocity /= velspeed;
6286 velspeed = speed * 12 * scale;
6287 velocity *= velspeed;
6289 velocity.y += gravity * multiplier * 20;
6290 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6291 velspeed = findLength(&velocity);
6292 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
6295 if (animTarget == staggerbackhighanim) {
6296 coords -= facing * multiplier * speed * 16 * scale;
6299 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
6300 coords -= facing * multiplier * speed * 20 * scale;
6304 if (animTarget == backhandspringanim) {
6305 //coords-=facing*multiplier*50*scale;
6306 velocity += facing * multiplier * speed * 700 * scale * -1;
6307 velspeed = findLength(&velocity);
6308 if (velspeed > speed * 50 * scale) {
6309 velocity /= velspeed;
6310 velspeed = speed * 50 * scale;
6311 velocity *= velspeed;
6313 velocity.y += gravity * multiplier * 20;
6314 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6315 velspeed = findLength(&velocity);
6316 velocity = flatfacing * velspeed * -1;
6318 if (animTarget == dodgebackanim) {
6319 //coords-=facing*multiplier*50*scale;
6320 velocity += facing * multiplier * speed * 700 * scale * -1;
6321 velspeed = findLength(&velocity);
6322 if (velspeed > speed * 60 * scale) {
6323 velocity /= velspeed;
6324 velspeed = speed * 60 * scale;
6325 velocity *= velspeed;
6327 velocity.y += gravity * multiplier * 20;
6328 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6329 velspeed = findLength(&velocity);
6330 velocity = flatfacing * velspeed * -1;
6333 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6334 velspeed = findLength(&velocity);
6337 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6338 velocity.y += gravity * multiplier;
6341 if (animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6342 coords += velocity * multiplier;
6345 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6346 if (isFlip() && targetFrame().label == 7) {
6350 if (animTarget == jumpupanim) {
6352 animTarget = getIdle();
6359 pause_sound(whooshsound);
6360 OPENAL_SetVolume(channels[whooshsound], 0);
6363 if (animTarget == jumpdownanim || isFlip()) {
6367 animTarget = getLanding();
6368 emit_sound_at(landsound, coords, 128.);
6371 addEnvSound(coords);
6376 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6377 coords.y += gravity * multiplier * 2;
6379 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
6380 coords.y = terrain.getHeight(coords.x, coords.z);
6384 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)) {
6385 velspeed = findLength(&velocity);
6387 if (velspeed < multiplier * 300 * scale) {
6390 velocity -= velocity / velspeed * multiplier * 300 * scale;
6392 if (velspeed > 5 && (isLanding() || isLandhard())) {
6393 skiddingdelay += multiplier;
6394 if (skiddelay <= 0) {
6395 FootLand(leftfoot, .5);
6396 FootLand(rightfoot, .5);
6405 velspeed = findLength(&velocity);
6407 if (velspeed > 5 && (isLanding() || isLandhard())) {
6408 skiddingdelay += multiplier;
6409 if (skiddelay <= 0) {
6410 FootLand(leftfoot, .5);
6411 FootLand(rightfoot, .5);
6419 if (skiddingdelay < 0) {
6420 skiddingdelay += multiplier;
6422 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
6424 if (!onterrain || environment == grassyenvironment) {
6425 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
6427 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
6431 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
6432 terrainnormal = victim->coords - coords;
6433 Normalise(&terrainnormal);
6434 targetyaw = -asin(0 - terrainnormal.x);
6435 targetyaw *= 360 / 6.28;
6436 if (terrainnormal.z < 0) {
6437 targetyaw = 180 - targetyaw;
6439 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
6442 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
6443 targetyaw = victim->targetyaw;
6445 if (animTarget == rabbittacklinganim) {
6446 coords = victim->coords;
6449 skeleton.oldfree = skeleton.free;
6453 midterrain.x = terrain.size * terrain.scale / 2;
6454 midterrain.z = terrain.size * terrain.scale / 2;
6455 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
6457 tempposit = coords - midterrain;
6459 Normalise(&tempposit);
6460 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
6461 coords.x = tempposit.x + midterrain.x;
6462 coords.z = tempposit.z + midterrain.z;
6467 * inverse kinematics helper function
6469 void IKHelper(Person* p, float interp)
6471 XYZ point, change, change2;
6472 float heightleft, heightright;
6474 // TODO: implement localToWorld and worldToLocal
6475 // but keep in mind it won't be the same math if player is ragdolled or something
6476 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
6477 // then comb through code for places where to use it
6479 // point = localToWorld(jointPos(leftfoot))
6480 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
6481 // adjust height of foot
6482 heightleft = terrain.getHeight(point.x, point.z) + .04;
6483 point.y = heightleft;
6484 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
6485 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
6486 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
6487 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
6488 // move ankle along with foot
6489 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
6490 // average knee pos between old and new pos
6491 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
6493 // do same as above for right leg
6494 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
6495 heightright = terrain.getHeight(point.x, point.z) + .04;
6496 point.y = heightright;
6497 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
6498 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
6499 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
6500 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
6501 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
6503 // fix up skeleton now that we've moved body parts?
6504 p->skeleton.DoConstraints(&p->coords, &p->scale);
6511 int Person::DrawSkeleton()
6513 int oldplayerdetail;
6514 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6515 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6525 glAlphaFunc(GL_GREATER, 0.0001);
6527 float terrainheight;
6529 if (!isnormal(yaw)) {
6532 if (!isnormal(tilt)) {
6535 if (!isnormal(tilt2)) {
6538 oldplayerdetail = playerdetail;
6540 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6543 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6546 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6552 if (playerdetail != oldplayerdetail) {
6554 normalsupdatedelay = 0;
6556 static float updatedelaychange;
6557 static float morphness;
6558 static float framemult;
6560 skeleton.FindForwards();
6561 if (howactive == typesittingwall) {
6562 skeleton.specialforward[1] = 0;
6563 skeleton.specialforward[1].z = 1;
6569 static int weaponattachmuscle;
6570 static int weaponrotatemuscle;
6571 static XYZ weaponpoint;
6572 static int start, endthing;
6573 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6574 if (!isSleeping() && !isSitting()) {
6575 // TODO: give these meaningful names
6576 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6577 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard() || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6579 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6581 if (creature == wolftype) {
6586 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6587 IKHelper(this, target);
6588 if (creature == wolftype) {
6589 IKHelper(this, target);
6593 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6594 IKHelper(this, 1 - target);
6595 if (creature == wolftype) {
6596 IKHelper(this, 1 - target);
6601 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())) {
6604 targetheadyaw = -targetyaw;
6605 targetheadpitch = 0;
6606 if (Animation::animations[animTarget].attack == 3) {
6607 targetheadyaw += 180;
6610 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6611 skeleton.drawmodel.vertex[i] = 0;
6612 skeleton.drawmodel.vertex[i].y = 999;
6614 for (int i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6615 skeleton.drawmodellow.vertex[i] = 0;
6616 skeleton.drawmodellow.vertex[i].y = 999;
6618 for (int i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6619 skeleton.drawmodelclothes.vertex[i] = 0;
6620 skeleton.drawmodelclothes.vertex[i].y = 999;
6622 for (unsigned int i = 0; i < skeleton.muscles.size(); i++) {
6623 // convenience renames
6624 const int p1 = skeleton.muscles[i].parent1->label;
6625 const int p2 = skeleton.muscles[i].parent2->label;
6627 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6632 if (p1 == righthand || p2 == righthand) {
6633 morphness = righthandmorphness;
6634 start = righthandmorphstart;
6635 endthing = righthandmorphend;
6637 if (p1 == lefthand || p2 == lefthand) {
6638 morphness = lefthandmorphness;
6639 start = lefthandmorphstart;
6640 endthing = lefthandmorphend;
6642 if (p1 == head || p2 == head) {
6643 morphness = headmorphness;
6644 start = headmorphstart;
6645 endthing = headmorphend;
6647 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6648 morphness = chestmorphness;
6649 start = chestmorphstart;
6650 endthing = chestmorphend;
6652 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6653 morphness = tailmorphness;
6654 start = tailmorphstart;
6655 endthing = tailmorphend;
6658 skeleton.FindRotationMuscle(i, animTarget);
6660 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6661 glMatrixMode(GL_MODELVIEW);
6664 if (!skeleton.free) {
6665 glRotatef(tilt2, 1, 0, 0);
6667 if (!skeleton.free) {
6668 glRotatef(tilt, 0, 0, 1);
6671 glTranslatef(mid.x, mid.y, mid.z);
6673 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6674 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6676 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6677 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6679 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6680 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6682 if (playerdetail || skeleton.free == 3) {
6683 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6684 XYZ& v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6685 XYZ& v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6686 glMatrixMode(GL_MODELVIEW);
6688 if (p1 == abdomen || p2 == abdomen) {
6689 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(1).x,
6690 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(1).y,
6691 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(1).z);
6693 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6694 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(2).x,
6695 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(2).y,
6696 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(2).z);
6698 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6699 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(3).x,
6700 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(3).y,
6701 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(3).z);
6703 if (p1 == head || p2 == head) {
6704 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(0).x,
6705 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(0).y,
6706 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(0).z);
6708 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6709 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6710 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6711 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6715 if (!playerdetail || skeleton.free == 3) {
6716 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6717 XYZ& v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6718 glMatrixMode(GL_MODELVIEW);
6720 if (p1 == abdomen || p2 == abdomen) {
6721 glTranslatef(v0.x * getProportion(1).x,
6722 v0.y * getProportion(1).y,
6723 v0.z * getProportion(1).z);
6725 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6726 glTranslatef(v0.x * getProportion(2).x,
6727 v0.y * getProportion(2).y,
6728 v0.z * getProportion(2).z);
6730 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6731 glTranslatef(v0.x * getProportion(3).x,
6732 v0.y * getProportion(3).y,
6733 v0.z * getProportion(3).z);
6735 if (p1 == head || p2 == head) {
6736 glTranslatef(v0.x * getProportion(0).x,
6737 v0.y * getProportion(0).y,
6738 v0.z * getProportion(0).z);
6741 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6742 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6743 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6744 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6750 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6751 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6753 glMatrixMode(GL_MODELVIEW);
6756 if (!skeleton.free) {
6757 glRotatef(tilt2, 1, 0, 0);
6759 if (!skeleton.free) {
6760 glRotatef(tilt, 0, 0, 1);
6762 glTranslatef(mid.x, mid.y, mid.z);
6763 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6764 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6766 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6767 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6769 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6770 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6772 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6773 XYZ& v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6774 glMatrixMode(GL_MODELVIEW);
6776 if (p1 == abdomen || p2 == abdomen) {
6777 glTranslatef(v0.x * getProportion(1).x,
6778 v0.y * getProportion(1).y,
6779 v0.z * getProportion(1).z);
6781 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6782 glTranslatef(v0.x * getProportion(2).x,
6783 v0.y * getProportion(2).y,
6784 v0.z * getProportion(2).z);
6786 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6787 glTranslatef(v0.x * getProportion(3).x,
6788 v0.y * getProportion(3).y,
6789 v0.z * getProportion(3).z);
6791 if (p1 == head || p2 == head) {
6792 glTranslatef(v0.x * getProportion(0).x,
6793 v0.y * getProportion(0).y,
6794 v0.z * getProportion(0).z);
6796 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6797 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6798 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6799 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6804 updatedelay = 1 + (float)(Random() % 100) / 1000;
6806 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6807 normalsupdatedelay = 1;
6808 if (playerdetail || skeleton.free == 3) {
6809 skeleton.drawmodel.CalculateNormals(0);
6811 if (!playerdetail || skeleton.free == 3) {
6812 skeleton.drawmodellow.CalculateNormals(0);
6814 if (skeleton.clothes) {
6815 skeleton.drawmodelclothes.CalculateNormals(0);
6818 if (playerdetail || skeleton.free == 3) {
6819 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6821 if (!playerdetail || skeleton.free == 3) {
6822 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6824 if (skeleton.clothes) {
6825 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6830 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6831 if (updatedelaychange > -realmultiplier * 30) {
6832 updatedelaychange = -realmultiplier * 30;
6834 if (updatedelaychange > -framemult * 4) {
6835 updatedelaychange = -framemult * 4;
6837 if (skeleton.free == 1) {
6838 updatedelaychange *= 6;
6841 updatedelaychange *= 8;
6843 updatedelay += updatedelaychange;
6845 glMatrixMode(GL_MODELVIEW);
6847 glTranslatef(coords.x, coords.y - .02, coords.z);
6848 if (!skeleton.free) {
6849 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6850 glRotatef(yaw, 0, 1, 0);
6854 glColor4f(.4, 1, .4, 1);
6855 glDisable(GL_LIGHTING);
6856 glDisable(GL_TEXTURE_2D);
6859 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6860 XYZ& v0 = skeleton.drawmodel.vertex[i];
6861 glVertex3f(v0.x, v0.y, v0.z);
6868 for (unsigned int i = 0; i < skeleton.drawmodel.Triangles.size(); i++) {
6869 const XYZ& v0 = skeleton.drawmodel.getTriangleVertex(i, 0);
6870 const XYZ& v1 = skeleton.drawmodel.getTriangleVertex(i, 1);
6871 const XYZ& v2 = skeleton.drawmodel.getTriangleVertex(i, 2);
6872 glVertex3f(v0.x, v0.y, v0.z);
6873 glVertex3f(v1.x, v1.y, v1.z);
6874 glVertex3f(v1.x, v1.y, v1.z);
6875 glVertex3f(v2.x, v2.y, v2.z);
6876 glVertex3f(v2.x, v2.y, v2.z);
6877 glVertex3f(v0.x, v0.y, v0.z);
6884 terrainlight = terrain.getLighting(coords.x, coords.z);
6885 distance = distsq(&viewer, &coords);
6886 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6891 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6892 if (terrainheight < 1) {
6895 if (terrainheight > 1.7) {
6896 terrainheight = 1.7;
6899 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6900 glDisable(GL_BLEND);
6901 glAlphaFunc(GL_GREATER, 0.0001);
6902 glEnable(GL_TEXTURE_2D);
6904 glDisable(GL_TEXTURE_2D);
6905 glColor4f(.7, .35, 0, .5);
6907 glEnable(GL_LIGHTING);
6910 if (Tutorial::active && id != 0) {
6911 glColor4f(.7, .7, .7, 0.6);
6913 glEnable(GL_LIGHTING);
6915 if (canattack && cananger) {
6916 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6917 glDisable(GL_TEXTURE_2D);
6918 glColor4f(1, 0, 0, 0.8);
6921 glMatrixMode(GL_TEXTURE);
6923 glTranslatef(0, -smoketex, 0);
6924 glTranslatef(-smoketex, 0, 0);
6928 if (Tutorial::active && (id != 0)) {
6929 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6931 skeleton.drawmodel.draw();
6935 if (!playerdetail) {
6936 if (Tutorial::active && (id != 0)) {
6937 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6939 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6943 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed)) {
6944 if (Tutorial::active && id != 0) {
6946 glMatrixMode(GL_MODELVIEW);
6947 glEnable(GL_TEXTURE_2D);
6948 glColor4f(.7, .7, .7, 0.6);
6950 glEnable(GL_LIGHTING);
6952 if (canattack && cananger) {
6953 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6954 glDisable(GL_TEXTURE_2D);
6955 glColor4f(1, 0, 0, 0.8);
6958 glMatrixMode(GL_TEXTURE);
6960 glTranslatef(0, -smoketex * .6, 0);
6961 glTranslatef(smoketex * .6, 0, 0);
6964 if (Tutorial::active && (id != 0)) {
6965 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6967 skeleton.drawmodel.draw();
6971 if (!playerdetail) {
6972 if (Tutorial::active && (id != 0)) {
6973 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6975 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6981 if (Tutorial::active && id != 0) {
6983 glMatrixMode(GL_MODELVIEW);
6984 glEnable(GL_TEXTURE_2D);
6986 if (skeleton.clothes) {
6990 skeleton.drawmodelclothes.draw();
6993 skeleton.drawmodelclothes.drawimmediate();
7000 if (num_weapons > 0) {
7001 for (k = 0; k < num_weapons; k++) {
7002 int i = weaponids[k];
7003 if (weaponactive == k) {
7004 if (weapons[i].getType() != staff) {
7005 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7006 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
7007 weaponattachmuscle = j;
7010 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7011 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) {
7012 weaponrotatemuscle = j;
7015 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
7016 if (creature == wolftype) {
7017 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
7020 if (weapons[i].getType() == staff) {
7021 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7022 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
7023 weaponattachmuscle = j;
7026 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7027 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) {
7028 weaponrotatemuscle = j;
7031 //weaponpoint=jointPos(rightwrist);
7032 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
7033 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
7034 XYZ tempnormthing, vec1, vec2;
7035 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
7036 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
7037 CrossProduct(&vec1, &vec2, &tempnormthing);
7038 Normalise(&tempnormthing);
7039 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim) {
7040 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
7044 if (weaponactive != k && weaponstuck != k) {
7045 if (weapons[i].getType() == knife) {
7046 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
7048 if (weapons[i].getType() == sword) {
7049 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
7051 if (weapons[i].getType() == staff) {
7052 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
7054 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7055 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) {
7056 weaponrotatemuscle = j;
7060 if (weaponstuck == k) {
7061 if (weaponstuckwhere == 0) {
7062 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
7064 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
7066 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7067 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) {
7068 weaponrotatemuscle = j;
7072 if (skeleton.free) {
7073 weapons[i].position = weaponpoint * scale + coords;
7074 weapons[i].bigrotation = 0;
7075 weapons[i].bigtilt = 0;
7076 weapons[i].bigtilt2 = 0;
7078 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;
7079 weapons[i].bigrotation = yaw;
7080 weapons[i].bigtilt = tilt;
7081 weapons[i].bigtilt2 = tilt2;
7083 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
7084 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
7085 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
7086 if (weaponactive == k) {
7087 if (weapons[i].getType() == knife) {
7088 weapons[i].smallrotation = 180;
7089 weapons[i].smallrotation2 = 0;
7090 if (isCrouch() || wasCrouch()) {
7091 weapons[i].smallrotation2 = 20;
7093 if (animTarget == hurtidleanim) {
7094 weapons[i].smallrotation2 = 50;
7096 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
7097 XYZ temppoint1, temppoint2;
7100 temppoint1 = jointPos(righthand);
7101 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7102 distance = findDistance(&temppoint1, &temppoint2);
7103 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7104 weapons[i].rotation2 *= 360 / 6.28;
7107 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7108 weapons[i].rotation1 *= 360 / 6.28;
7109 weapons[i].rotation3 = 0;
7110 weapons[i].smallrotation = -90;
7111 weapons[i].smallrotation2 = 0;
7112 if (temppoint1.x > temppoint2.x) {
7113 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7116 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
7117 XYZ temppoint1, temppoint2;
7120 temppoint1 = jointPos(righthand);
7121 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7122 distance = findDistance(&temppoint1, &temppoint2);
7123 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7124 weapons[i].rotation2 *= 360 / 6.28;
7127 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7128 weapons[i].rotation1 *= 360 / 6.28;
7129 weapons[i].rotation3 = 0;
7130 weapons[i].smallrotation = 90;
7131 weapons[i].smallrotation2 = 0;
7132 if (temppoint1.x > temppoint2.x) {
7133 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7136 if (animTarget == knifethrowanim) {
7137 weapons[i].smallrotation = 90;
7138 //weapons[i].smallrotation2=-90;
7139 weapons[i].smallrotation2 = 0;
7140 weapons[i].rotation1 = 0;
7141 weapons[i].rotation2 = 0;
7142 weapons[i].rotation3 = 0;
7144 if (animTarget == knifesneakattackanim && frameTarget < 5) {
7145 weapons[i].smallrotation = -90;
7146 weapons[i].rotation1 = 0;
7147 weapons[i].rotation2 = 0;
7148 weapons[i].rotation3 = 0;
7151 if (weapons[i].getType() == sword) {
7152 weapons[i].smallrotation = 0;
7153 weapons[i].smallrotation2 = 0;
7154 if (animTarget == knifethrowanim) {
7155 weapons[i].smallrotation = -90;
7156 weapons[i].smallrotation2 = 0;
7157 weapons[i].rotation1 = 0;
7158 weapons[i].rotation2 = 0;
7159 weapons[i].rotation3 = 0;
7161 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)) {
7162 XYZ temppoint1, temppoint2;
7165 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
7166 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7167 distance = findDistance(&temppoint1, &temppoint2);
7168 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7169 weapons[i].rotation2 *= 360 / 6.28;
7172 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7173 weapons[i].rotation1 *= 360 / 6.28;
7174 weapons[i].rotation3 = 0;
7175 weapons[i].smallrotation = 90;
7176 weapons[i].smallrotation2 = 0;
7177 if (temppoint1.x > temppoint2.x) {
7178 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7182 if (weapons[i].getType() == staff) {
7183 weapons[i].smallrotation = 100;
7184 weapons[i].smallrotation2 = 0;
7185 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
7186 XYZ temppoint1, temppoint2;
7189 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
7190 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7191 distance = findDistance(&temppoint1, &temppoint2);
7192 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7193 weapons[i].rotation2 *= 360 / 6.28;
7196 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7197 weapons[i].rotation1 *= 360 / 6.28;
7198 weapons[i].rotation3 = 0;
7199 weapons[i].smallrotation = 90;
7200 weapons[i].smallrotation2 = 0;
7201 if (temppoint1.x > temppoint2.x) {
7202 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7207 if (weaponactive != k && weaponstuck != k) {
7208 if (weapons[i].getType() == knife) {
7209 weapons[i].smallrotation = -70;
7210 weapons[i].smallrotation2 = 10;
7212 if (weapons[i].getType() == sword) {
7213 weapons[i].smallrotation = -100;
7214 weapons[i].smallrotation2 = -8;
7216 if (weapons[i].getType() == staff) {
7217 weapons[i].smallrotation = -100;
7218 weapons[i].smallrotation2 = -8;
7221 if (weaponstuck == k) {
7222 if (weaponstuckwhere == 0) {
7223 weapons[i].smallrotation = 180;
7225 weapons[i].smallrotation = 0;
7227 weapons[i].smallrotation2 = 10;
7234 if (skeleton.free) {
7237 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump()) {
7240 if (animCurrent != animTarget) {
7243 if (skeleton.free == 2) {
7252 int Person::SphereCheck(XYZ* p1, float radius, XYZ* p, XYZ* move, float* rotate, Model* model)
7254 static float distance;
7255 static float olddistance;
7256 static int intersecting;
7257 static int firstintersecting;
7260 static XYZ start, end;
7261 static float slopethreshold = -.4;
7263 firstintersecting = -1;
7267 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius) {
7271 *p1 = DoRotation(*p1, 0, -*rotate, 0);
7273 for (int i = 0; i < 4; i++) {
7274 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7275 if (model->Triangles[j].facenormal.y <= slopethreshold) {
7277 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)));
7278 if (distance < radius) {
7279 point = *p1 - model->Triangles[j].facenormal * distance;
7280 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]])) {
7283 if (!intersecting) {
7284 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7285 &model->vertex[model->Triangles[j].vertex[1]],
7288 if (!intersecting) {
7289 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
7290 &model->vertex[model->Triangles[j].vertex[2]],
7293 if (!intersecting) {
7294 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7295 &model->vertex[model->Triangles[j].vertex[2]],
7299 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7303 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)) {
7304 p1->y = point.y + radius;
7305 if ((animTarget == jumpdownanim || isFlip())) {
7306 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4)) {
7310 if (animTarget == jumpupanim) {
7312 animTarget = getIdle();
7319 pause_sound(whooshsound);
7320 OPENAL_SetVolume(channels[whooshsound], 0);
7323 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
7327 animTarget = getLanding();
7328 emit_sound_at(landsound, coords, 128.);
7331 addEnvSound(coords);
7338 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7339 olddistance = distance;
7340 firstintersecting = j;
7345 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7346 if (model->Triangles[j].facenormal.y > slopethreshold) {
7349 start.y -= radius / 4;
7350 XYZ& v0 = model->vertex[model->Triangles[j].vertex[0]];
7351 XYZ& v1 = model->vertex[model->Triangles[j].vertex[1]];
7352 XYZ& v2 = model->vertex[model->Triangles[j].vertex[2]];
7353 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)));
7354 if (distance < radius * .5) {
7355 point = start - model->Triangles[j].facenormal * distance;
7356 if (PointInTriangle(&point, model->Triangles[j].facenormal, &v0, &v1, &v2)) {
7359 if (!intersecting) {
7360 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
7362 if (!intersecting) {
7363 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7365 if (!intersecting) {
7366 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7369 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7370 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
7372 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;
7373 if (findLengthfast(&start) < findLengthfast(&velocity)) {
7377 *p1 += model->Triangles[j].facenormal * (distance - radius * .5);
7380 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7381 olddistance = distance;
7382 firstintersecting = j;
7389 *p = DoRotation(*p, 0, *rotate, 0);
7393 *p1 = DoRotation(*p1, 0, *rotate, 0);
7396 return firstintersecting;
7399 int findPathDist(int start, int end)
7404 unsigned int smallestcount = 1000;
7405 for (char i = 0; i < 50; i++) {
7406 unsigned int count = 0;
7411 while (last != end && count < 30) {
7413 for (int j = 0; j < Game::numpathpoints; j++) {
7414 if (j != last && j != last2 && j != last3 && j != last4) {
7416 if (Game::numpathpointconnect[j]) {
7417 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7418 if (Game::pathpointconnect[j][k] == last) {
7424 if (Game::numpathpointconnect[last]) {
7425 for (int k = 0; k < Game::numpathpointconnect[last]; k++) {
7426 if (Game::pathpointconnect[last][k] == j) {
7433 if (closest == -1 || Random() % 2 == 0) {
7445 if (count < smallestcount) {
7446 smallestcount = count;
7449 return smallestcount;
7452 void Person::takeWeapon(int weaponId)
7455 weapons[weaponId].owner = id;
7456 if (num_weapons > 0) {
7457 weaponids[num_weapons] = weaponids[0];
7460 weaponids[0] = weaponId;
7463 void Person::addClothes()
7465 if (numclothes > 0) {
7466 for (int i = 0; i < numclothes; i++) {
7473 bool Person::addClothes(const int& clothesId)
7476 const std::string fileName = clothes[clothesId];
7478 GLubyte* array = &skeleton.skinText[0];
7482 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
7487 float tintr = clothestintr[clothesId];
7488 float tintg = clothestintg[clothesId];
7489 float tintb = clothestintb[clothesId];
7511 int bytesPerPixel = texture.bpp / 8;
7515 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
7516 if (bytesPerPixel == 3) {
7518 } else if ((i + 1) % 4 == 0) {
7519 alphanum = texture.data[i];
7521 if ((i + 1) % 4 || bytesPerPixel == 3) {
7523 texture.data[i] *= tintr;
7526 texture.data[i] *= tintg;
7529 texture.data[i] *= tintb;
7531 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
7543 if (aitype != playercontrolled && !Dialog::inDialog()) {
7545 //disable movement in editor
7546 if (Game::editorenabled) {
7551 if (distsqflat(&Person::players[0]->coords, &coords) < 30 &&
7552 Person::players[0]->coords.y > coords.y + 2 &&
7553 !Person::players[0]->onterrain) {
7558 if (aitype == pathfindtype) {
7559 if (finalpathfindpoint == -1) {
7560 float closestdistance;
7561 float tempdist = 0.0f;
7565 closestdistance = -1;
7566 for (int j = 0; j < Game::numpathpoints; j++) {
7567 if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) {
7568 closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]);
7570 finaltarget = Game::pathpoint[j];
7573 finalpathfindpoint = closest;
7574 for (int j = 0; j < Game::numpathpoints; j++) {
7575 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7576 DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7577 if (sq(tempdist) < closestdistance) {
7578 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7579 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7580 closestdistance = sq(tempdist);
7582 finaltarget = colpoint;
7587 finalpathfindpoint = closest;
7589 if (targetpathfindpoint == -1) {
7590 float closestdistance;
7591 float tempdist = 0.0f;
7595 closestdistance = -1;
7596 if (lastpathfindpoint == -1) {
7597 for (int j = 0; j < Game::numpathpoints; j++) {
7598 if (j != lastpathfindpoint) {
7599 if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) {
7600 closestdistance = distsq(&coords, &Game::pathpoint[j]);
7605 targetpathfindpoint = closest;
7606 for (int j = 0; j < Game::numpathpoints; j++) {
7607 if (j != lastpathfindpoint) {
7608 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7609 DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7610 if (sq(tempdist) < closestdistance) {
7611 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7612 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7613 closestdistance = sq(tempdist);
7620 targetpathfindpoint = closest;
7622 for (int j = 0; j < Game::numpathpoints; j++) {
7623 if (j != lastpathfindpoint &&
7624 j != lastpathfindpoint2 &&
7625 j != lastpathfindpoint3 &&
7626 j != lastpathfindpoint4) {
7628 if (Game::numpathpointconnect[j]) {
7629 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7630 if (Game::pathpointconnect[j][k] == lastpathfindpoint) {
7636 if (Game::numpathpointconnect[lastpathfindpoint]) {
7637 for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++) {
7638 if (Game::pathpointconnect[lastpathfindpoint][k] == j) {
7645 tempdist = findPathDist(j, finalpathfindpoint);
7646 if (closest == -1 || tempdist < closestdistance) {
7647 closestdistance = tempdist;
7653 targetpathfindpoint = closest;
7656 losupdatedelay -= multiplier;
7658 targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]);
7659 lookyaw = targetyaw;
7661 //reached target point
7662 if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) {
7663 lastpathfindpoint4 = lastpathfindpoint3;
7664 lastpathfindpoint3 = lastpathfindpoint2;
7665 lastpathfindpoint2 = lastpathfindpoint;
7666 lastpathfindpoint = targetpathfindpoint;
7667 if (lastpathfindpoint2 == -1) {
7668 lastpathfindpoint2 = lastpathfindpoint;
7670 if (lastpathfindpoint3 == -1) {
7671 lastpathfindpoint3 = lastpathfindpoint2;
7673 if (lastpathfindpoint4 == -1) {
7674 lastpathfindpoint4 = lastpathfindpoint3;
7676 targetpathfindpoint = -1;
7678 if (distsqflat(&coords, &finalfinaltarget) <
7679 distsqflat(&coords, &finaltarget) ||
7680 distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) ||
7681 lastpathfindpoint == finalpathfindpoint) {
7682 aitype = passivetype;
7693 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7694 targetyaw += 90 * (whichdirection * 2 - 1);
7697 if (collided < 1 || animTarget != jumpupanim) {
7700 if ((collided > .8 && jumppower >= 5)) {
7704 if ((!Tutorial::active || cananger) &&
7706 !Person::players[0]->dead &&
7707 distsq(&coords, &Person::players[0]->coords) < 400 &&
7709 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7710 Animation::animations[Person::players[0]->animTarget].height != lowheight &&
7711 !Game::editorenabled &&
7712 (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain)) {
7713 aitype = attacktypecutoff;
7715 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7716 Animation::animations[Person::players[0]->animTarget].height == highheight &&
7717 !Game::editorenabled) {
7718 aitype = attacktypecutoff;
7721 if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7722 losupdatedelay = .2;
7723 for (unsigned j = 0; j < Person::players.size(); j++) {
7724 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7725 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7726 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7727 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7728 if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain) {
7729 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) ||
7730 (Person::players[j]->animTarget == hanganim &&
7731 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7732 aitype = searchtype;
7734 lastseen = Person::players[j]->coords;
7745 if (aitype == attacktypecutoff && Game::musictype != 2) {
7746 if (creature != wolftype) {
7753 if (aitype != passivetype && Game::leveltime > .5) {
7754 howactive = typeactive;
7757 if (aitype == passivetype) {
7758 aiupdatedelay -= multiplier;
7759 losupdatedelay -= multiplier;
7760 lastseentime += multiplier;
7761 pausetime -= multiplier;
7762 if (lastseentime > 1) {
7766 if (aiupdatedelay < 0) {
7767 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7768 targetyaw = roughDirectionTo(coords, waypoints[waypoint]);
7769 lookyaw = targetyaw;
7770 aiupdatedelay = .05;
7772 if (distsqflat(&coords, &waypoints[waypoint]) < 1) {
7773 if (waypointtype[waypoint] == wppause) {
7777 if (waypoint > numwaypoints - 1) {
7783 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7795 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7796 if (!avoidsomething) {
7797 targetyaw += 90 * (whichdirection * 2 - 1);
7799 XYZ leftpos, rightpos;
7800 float leftdist, rightdist;
7801 leftpos = coords + DoRotation(facing, 0, 90, 0);
7802 rightpos = coords - DoRotation(facing, 0, 90, 0);
7803 leftdist = distsq(&leftpos, &avoidwhere);
7804 rightdist = distsq(&rightpos, &avoidwhere);
7805 if (leftdist < rightdist) {
7813 if (collided < 1 || animTarget != jumpupanim) {
7816 if ((collided > .8 && jumppower >= 5)) {
7821 if (!Game::editorenabled) {
7822 if (howactive <= typesleeping) {
7823 if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile) {
7824 for (int j = 0; j < numenvsounds; j++) {
7825 float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
7826 if (vol > 0 && distsq(&coords, &envsound[j]) < 2 * (vol + vol * (creature == rabbittype) * 3)) {
7827 aitype = attacktypecutoff;
7833 if (aitype != passivetype) {
7834 if (howactive == typesleeping) {
7835 setTargetAnimation(getupfromfrontanim);
7837 howactive = typeactive;
7841 if (howactive < typesleeping &&
7842 ((!Tutorial::active || cananger) && hostile) &&
7843 !Person::players[0]->dead &&
7844 distsq(&coords, &Person::players[0]->coords) < 400 &&
7846 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7847 Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled) {
7848 aitype = attacktypecutoff;
7850 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7851 Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled) {
7852 aitype = attacktypecutoff;
7856 if (creature == wolftype) {
7858 for (unsigned j = 0; j < Person::players.size(); j++) {
7859 if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
7860 float smelldistance = 50;
7861 if (j == 0 && Person::players[j]->num_weapons > 0) {
7862 if (weapons[Person::players[j]->weaponids[0]].bloody) {
7863 smelldistance = 100;
7865 if (Person::players[j]->num_weapons == 2) {
7866 if (weapons[Person::players[j]->weaponids[1]].bloody) {
7867 smelldistance = 100;
7872 smelldistance = 100;
7874 windsmell = windvector;
7875 Normalise(&windsmell);
7876 windsmell = windsmell * 2 + Person::players[j]->coords;
7877 if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled) {
7878 aitype = attacktypecutoff;
7884 if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7885 losupdatedelay = .2;
7886 for (unsigned j = 0; j < Person::players.size(); j++) {
7887 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7888 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7889 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7890 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7891 if ((-1 == Object::checkcollide(
7892 DoRotation(jointPos(head), 0, yaw, 0) *
7895 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0) *
7896 Person::players[j]->scale +
7897 Person::players[j]->coords) &&
7898 !Person::players[j]->isWallJump()) ||
7899 (Person::players[j]->animTarget == hanganim &&
7900 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7902 if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight) {
7911 if (lastseentime <= 0) {
7912 aitype = searchtype;
7914 lastseen = Person::players[j]->coords;
7922 if (aitype == attacktypecutoff && Game::musictype != 2) {
7923 if (creature != wolftype) {
7927 if (creature == wolftype) {
7937 if (aitype == searchtype) {
7938 aiupdatedelay -= multiplier;
7939 losupdatedelay -= multiplier;
7941 lastseentime -= multiplier;
7943 lastchecktime -= multiplier;
7945 if (isRun() && !onground) {
7946 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7947 XYZ test2 = coords + facing;
7949 XYZ test = coords + facing;
7951 j = Object::checkcollide(test2, test, laststanding);
7953 j = Object::checkcollide(test2, test);
7957 setTargetAnimation(getStop());
7960 //aitype=passivetype;
7961 aitype = pathfindtype;
7962 finalfinaltarget = waypoints[waypoint];
7963 finalpathfindpoint = -1;
7964 targetpathfindpoint = -1;
7965 lastpathfindpoint = -1;
7966 lastpathfindpoint2 = -1;
7967 lastpathfindpoint3 = -1;
7968 lastpathfindpoint4 = -1;
7974 //check out last seen location
7975 if (aiupdatedelay < 0) {
7976 targetyaw = roughDirectionTo(coords, lastseen);
7977 lookyaw = targetyaw;
7978 aiupdatedelay = .05;
7981 if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) {
7984 lastseen.x += (float(Random() % 100) - 50) / 25;
7985 lastseen.z += (float(Random() % 100) - 50) / 25;
7996 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7997 if (!avoidsomething) {
7998 targetyaw += 90 * (whichdirection * 2 - 1);
8000 XYZ leftpos, rightpos;
8001 float leftdist, rightdist;
8002 leftpos = coords + DoRotation(facing, 0, 90, 0);
8003 rightpos = coords - DoRotation(facing, 0, 90, 0);
8004 leftdist = distsq(&leftpos, &avoidwhere);
8005 rightdist = distsq(&rightpos, &avoidwhere);
8006 if (leftdist < rightdist) {
8014 if (collided < 1 || animTarget != jumpupanim) {
8017 if ((collided > .8 && jumppower >= 5)) {
8021 if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile)) {
8022 for (int k = 0; k < numenvsounds; k++) {
8023 if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) {
8024 aitype = attacktypecutoff;
8029 if (!Person::players[0]->dead &&
8030 losupdatedelay < 0 &&
8031 !Game::editorenabled &&
8033 ((!Tutorial::active || cananger) && hostile)) {
8034 losupdatedelay = .2;
8035 if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) {
8036 aitype = attacktypecutoff;
8039 if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight) {
8040 //TODO: factor out canSeePlayer()
8041 if (distsq(&coords, &Person::players[0]->coords) < 400) {
8042 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
8043 if ((Object::checkcollide(
8044 DoRotation(jointPos(head), 0, yaw, 0) *
8047 DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0) *
8048 Person::players[0]->scale +
8049 Person::players[0]->coords) == -1) ||
8050 (Person::players[0]->animTarget == hanganim && normaldotproduct(Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) {
8051 /* //TODO: changed j to 0 on a whim, make sure this is correct
8052 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
8053 Person::players[j]->facing,coords-Person::players[j]->coords)<0)
8055 aitype = attacktypecutoff;
8063 if (lastseentime < 0) {
8064 //aitype=passivetype;
8066 aitype = pathfindtype;
8067 finalfinaltarget = waypoints[waypoint];
8068 finalpathfindpoint = -1;
8069 targetpathfindpoint = -1;
8070 lastpathfindpoint = -1;
8071 lastpathfindpoint2 = -1;
8072 lastpathfindpoint3 = -1;
8073 lastpathfindpoint4 = -1;
8077 if (aitype != gethelptype) {
8081 //get help from buddies
8082 if (aitype == gethelptype) {
8083 runninghowlong += multiplier;
8084 aiupdatedelay -= multiplier;
8086 if (aiupdatedelay < 0 || ally == 0) {
8090 //TODO: factor out closest search somehow
8093 float closestdist = -1;
8094 for (unsigned k = 0; k < Person::players.size(); k++) {
8095 if ((k != id) && (k != 0) && !Person::players[k]->dead &&
8096 (Person::players[k]->howactive < typedead1) &&
8097 !Person::players[k]->skeleton.free &&
8098 (Person::players[k]->aitype == passivetype)) {
8099 float distance = distsq(&coords, &Person::players[k]->coords);
8100 if (closestdist == -1 || distance < closestdist) {
8101 closestdist = distance;
8106 if (closest != -1) {
8111 lastseen = Person::players[0]->coords;
8117 XYZ facing = coords;
8118 XYZ flatfacing = Person::players[ally]->coords;
8119 facing.y += jointPos(head).y * scale;
8120 flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale;
8121 if (-1 != Object::checkcollide(facing, flatfacing)) {
8125 //no available ally, run back to player
8127 Person::players[ally]->skeleton.free ||
8128 Person::players[ally]->aitype != passivetype ||
8129 lastseentime <= 0) {
8130 aitype = searchtype;
8136 targetyaw = roughDirectionTo(coords, Person::players[ally]->coords);
8137 lookyaw = targetyaw;
8138 aiupdatedelay = .05;
8141 if (distsqflat(&coords, &Person::players[ally]->coords) < 3) {
8142 aitype = searchtype;
8144 Person::players[ally]->aitype = searchtype;
8145 if (Person::players[ally]->lastseentime < lastseentime) {
8146 Person::players[ally]->lastseen = lastseen;
8147 Person::players[ally]->lastseentime = lastseentime;
8148 Person::players[ally]->lastchecktime = lastchecktime;
8152 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8153 if (!avoidsomething) {
8154 targetyaw += 90 * (whichdirection * 2 - 1);
8156 XYZ leftpos, rightpos;
8157 float leftdist, rightdist;
8158 leftpos = coords + DoRotation(facing, 0, 90, 0);
8159 rightpos = coords - DoRotation(facing, 0, 90, 0);
8160 leftdist = distsq(&leftpos, &avoidwhere);
8161 rightdist = distsq(&rightpos, &avoidwhere);
8162 if (leftdist < rightdist) {
8177 if (collided < 1 || animTarget != jumpupanim) {
8180 if (collided > .8 && jumppower >= 5) {
8185 //retreiving a weapon on the ground
8186 if (aitype == getweapontype) {
8187 aiupdatedelay -= multiplier;
8188 lastchecktime -= multiplier;
8190 if (aiupdatedelay < 0) {
8196 float closestdist = -1;
8197 for (unsigned k = 0; k < weapons.size(); k++) {
8198 if (weapons[k].owner == -1) {
8199 float distance = distsq(&coords, &weapons[k].position);
8200 if (closestdist == -1 || distance < closestdist) {
8201 closestdist = distance;
8206 if (closest != -1) {
8215 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile)) {
8216 if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) {
8217 aitype = attacktypecutoff;
8221 if (!Person::players[0]->dead) {
8223 if (weapons[ally].owner != -1 ||
8224 distsq(&coords, &weapons[ally].position) > 16) {
8225 aitype = attacktypecutoff;
8228 //TODO: factor these out as moveToward()
8229 targetyaw = roughDirectionTo(coords, weapons[ally].position);
8230 lookyaw = targetyaw;
8231 aiupdatedelay = .05;
8234 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8235 if (!avoidsomething) {
8236 targetyaw += 90 * (whichdirection * 2 - 1);
8238 XYZ leftpos, rightpos;
8239 float leftdist, rightdist;
8240 leftpos = coords + DoRotation(facing, 0, 90, 0);
8241 rightpos = coords - DoRotation(facing, 0, 90, 0);
8242 leftdist = distsq(&leftpos, &avoidwhere);
8243 rightdist = distsq(&rightpos, &avoidwhere);
8244 if (leftdist < rightdist) {
8260 if (animTarget != crouchremoveknifeanim &&
8261 animTarget != removeknifeanim) {
8262 throwtogglekeydown = 0;
8266 if (collided < 1 || animTarget != jumpupanim) {
8269 if ((collided > .8 && jumppower >= 5)) {
8274 if (aitype == attacktypecutoff) {
8275 aiupdatedelay -= multiplier;
8276 //dodge or reverse rabbit kicks, knife throws, flips
8277 if (damage < damagetolerance * 2 / 3) {
8278 if ((Person::players[0]->animTarget == rabbitkickanim ||
8279 Person::players[0]->animTarget == knifethrowanim ||
8280 (Person::players[0]->isFlip() &&
8281 normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) &&
8282 !Person::players[0]->skeleton.free &&
8283 (aiupdatedelay < .1)) {
8288 if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
8289 if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
8290 if (isIdle() || isCrouch() || isRun() || isFlip()) {
8291 if (abs(Random() % 2) == 0) {
8292 setTargetAnimation(backhandspringanim);
8294 setTargetAnimation(rollanim);
8296 targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
8299 if (animTarget == jumpupanim || animTarget == jumpdownanim) {
8300 setTargetAnimation(flipanim);
8305 aiupdatedelay = .02;
8308 //get confused by flips
8309 if (Person::players[0]->isFlip() &&
8310 !Person::players[0]->skeleton.free &&
8311 Person::players[0]->animTarget != walljumprightkickanim &&
8312 Person::players[0]->animTarget != walljumpleftkickanim) {
8313 if (distsq(&Person::players[0]->coords, &coords) < 25) {
8314 if ((1 - damage / damagetolerance) > .5) {
8319 //go for weapon on the ground
8320 if (wentforweapon < 3) {
8321 for (unsigned k = 0; k < weapons.size(); k++) {
8322 if (creature != wolftype) {
8323 if (num_weapons == 0 &&
8324 weapons[k].owner == -1 &&
8325 weapons[k].velocity.x == 0 &&
8326 weapons[k].velocity.z == 0 &&
8327 weapons[k].velocity.y == 0) {
8328 if (distsq(&coords, &weapons[k].position) < 16) {
8331 aitype = getweapontype;
8338 //dodge/reverse walljump kicks
8339 if (damage < damagetolerance / 2) {
8340 if (Animation::animations[animTarget].height != highheight) {
8341 if (damage < damagetolerance * .5 &&
8342 ((Person::players[0]->animTarget == walljumprightkickanim ||
8343 Person::players[0]->animTarget == walljumpleftkickanim) &&
8344 ((aiupdatedelay < .15 &&
8346 (aiupdatedelay < .08 &&
8347 difficulty != 2)))) {
8352 //walked off a ledge (?)
8353 if (isRun() && !onground) {
8354 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
8355 XYZ test2 = coords + facing;
8357 XYZ test = coords + facing;
8359 j = Object::checkcollide(test2, test, laststanding);
8361 j = Object::checkcollide(test2, test);
8365 setTargetAnimation(getStop());
8368 aitype = pathfindtype;
8369 finalfinaltarget = waypoints[waypoint];
8370 finalpathfindpoint = -1;
8371 targetpathfindpoint = -1;
8372 lastpathfindpoint = -1;
8373 lastpathfindpoint2 = -1;
8374 lastpathfindpoint3 = -1;
8375 lastpathfindpoint4 = -1;
8381 //lose sight of player in the air (?)
8382 if (Person::players[0]->coords.y > coords.y + 5 &&
8383 Animation::animations[Person::players[0]->animTarget].height != highheight &&
8384 !Person::players[0]->onterrain) {
8385 aitype = pathfindtype;
8386 finalfinaltarget = waypoints[waypoint];
8387 finalpathfindpoint = -1;
8388 targetpathfindpoint = -1;
8389 lastpathfindpoint = -1;
8390 lastpathfindpoint2 = -1;
8391 lastpathfindpoint3 = -1;
8392 lastpathfindpoint4 = -1;
8394 //it's time to think (?)
8395 if (aiupdatedelay < 0 &&
8396 !Animation::animations[animTarget].attack &&
8397 animTarget != staggerbackhighanim &&
8398 animTarget != staggerbackhardanim &&
8399 animTarget != backhandspringanim &&
8400 animTarget != dodgebackanim) {
8402 if (weaponactive == -1 && num_weapons > 0) {
8403 drawkeydown = Random() % 2;
8407 rabbitkickenabled = Random() % 2;
8409 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
8410 XYZ targetpoint = Person::players[0]->coords;
8411 float vellength = findLength(&velocity);
8412 if (vellength != 0 &&
8413 distsq(&Person::players[0]->coords, &coords) < distsq(&rotatetarget, &coords)) {
8414 targetpoint += Person::players[0]->velocity *
8415 findDistance(&Person::players[0]->coords, &coords) / vellength;
8417 targetyaw = roughDirectionTo(coords, targetpoint);
8418 lookyaw = targetyaw;
8419 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
8421 if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1)) {
8423 } else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
8424 distsq(&coords, &Person::players[0]->coords) < 9) &&
8425 Person::players[0]->weaponactive != -1) {
8427 } else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0)) {
8432 //chill out around the corpse
8433 if (Person::players[0]->dead) {
8435 if (Random() % 10 == 0) {
8438 if (Random() % 100 == 0) {
8439 aitype = pathfindtype;
8440 finalfinaltarget = waypoints[waypoint];
8441 finalpathfindpoint = -1;
8442 targetpathfindpoint = -1;
8443 lastpathfindpoint = -1;
8444 lastpathfindpoint2 = -1;
8445 lastpathfindpoint3 = -1;
8446 lastpathfindpoint4 = -1;
8455 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8456 targetyaw += 90 * (whichdirection * 2 - 1);
8459 if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype) {
8464 if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7) {
8469 if (aitype != playercontrolled &&
8474 for (unsigned j = 0; j < Person::players.size(); j++) {
8475 if (j != id && !Person::players[j]->skeleton.free &&
8476 Person::players[j]->hasvictim &&
8477 (Tutorial::active && reversaltrain ||
8478 Random() % 2 == 0 && difficulty == 2 ||
8479 Random() % 4 == 0 && difficulty == 1 ||
8480 Random() % 8 == 0 && difficulty == 0 ||
8481 Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
8482 Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
8483 (Random() % 2 == 0 || difficulty == 2) ||
8484 (isIdle() || isRun()) &&
8485 Person::players[j]->weaponactive != -1 ||
8486 Person::players[j]->animTarget == swordslashanim &&
8487 weaponactive != -1 ||
8488 Person::players[j]->animTarget == staffhitanim ||
8489 Person::players[j]->animTarget == staffspinhitanim)) {
8490 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
8491 Person::players[j]->victim == Person::players[id] &&
8492 (Person::players[j]->animTarget == sweepanim ||
8493 Person::players[j]->animTarget == spinkickanim ||
8494 Person::players[j]->animTarget == staffhitanim ||
8495 Person::players[j]->animTarget == staffspinhitanim ||
8496 Person::players[j]->animTarget == winduppunchanim ||
8497 Person::players[j]->animTarget == upunchanim ||
8498 Person::players[j]->animTarget == wolfslapanim ||
8499 Person::players[j]->animTarget == knifeslashstartanim ||
8500 Person::players[j]->animTarget == swordslashanim &&
8501 (distsq(&Person::players[j]->coords, &coords) < 2 ||
8502 weaponactive != -1))) {
8512 Person::players[target]->Reverse();
8519 if (collided > .8 && jumppower >= 5 ||
8520 distsq(&coords, &Person::players[0]->coords) > 400 &&
8522 creature == rabbittype) {
8525 //TODO: why are we controlling the human?
8526 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
8527 Person::players[0]->jumpkeydown = 0;
8529 if (Person::players[0]->animTarget == jumpdownanim &&
8530 distsq(&Person::players[0]->coords, &coords) < 40) {
8537 if (Tutorial::active) {
8543 XYZ facing = coords;
8544 XYZ flatfacing = Person::players[0]->coords;
8545 facing.y += jointPos(head).y * scale;
8546 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
8547 if (occluded >= 2) {
8548 if (-1 != Object::checkcollide(facing, flatfacing)) {
8552 if (lastseentime <= 0 &&
8553 (creature != wolftype ||
8554 weaponstuck == -1)) {
8555 aitype = searchtype;
8557 lastseen = Person::players[0]->coords;
8566 if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
8567 (aitype == attacktypecutoff ||
8568 aitype == searchtype)) {
8569 if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
8570 XYZ test = Person::players[0]->coords;
8572 if (-1 == Object::checkcollide(Person::players[0]->coords, test)) {
8578 if (aitype == passivetype && !(numwaypoints > 1) ||
8580 pause && damage > superpermanentdamage) {
8599 XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0);
8600 facing = flatfacing;
8602 if (aitype == attacktypecutoff) {
8603 targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
8604 targetheadpitch = pitchTo(coords, Person::players[0]->coords);
8605 } else if (howactive >= typesleeping) {
8606 targetheadyaw = targetyaw;
8607 targetheadpitch = 0;
8609 if (interestdelay <= 0) {
8610 interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
8611 headtarget = coords;
8612 headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
8613 headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
8614 headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
8615 headtarget += facing * 1.5;
8617 targetheadyaw = 180 - roughDirectionTo(coords, headtarget);
8618 targetheadpitch = pitchTo(coords, headtarget);