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 int bloodtoggle;
46 extern bool autoslomo;
47 extern float camerashake;
49 extern float viewdistance;
50 extern float blackout;
51 extern int difficulty;
52 extern bool decalstoggle;
53 extern float fadestart;
55 extern bool winfreeze;
56 extern bool showpoints;
57 extern bool immediate;
58 extern float smoketex;
59 extern bool reversaltrain;
60 extern bool canattack;
62 extern float damagedealt;
64 extern float hostiletime;
66 extern bool gamestarted;
68 extern XYZ envsound[30];
69 extern float envsoundvol[30];
70 extern int numenvsounds;
71 extern float envsoundlife[30];
73 extern XYZ windvector;
75 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
76 std::vector<PersonType> PersonType::types;
78 void PersonType::Load()
83 types[wolftype].proportions[0] = 1.1;
84 types[wolftype].proportions[1] = 1.1;
85 types[wolftype].proportions[2] = 1.1;
86 types[wolftype].proportions[3] = 1.1;
88 types[wolftype].animRun = wolfrunanim;
89 types[wolftype].animRunning = wolfrunninganim;
90 types[wolftype].animCrouch = wolfcrouchanim;
91 types[wolftype].animStop = wolfstopanim;
92 types[wolftype].animLanding = wolflandanim;
93 types[wolftype].animLandingHard = wolflandhardanim;
95 types[wolftype].soundsAttack[0] = barksound;
96 types[wolftype].soundsAttack[1] = bark2sound;
97 types[wolftype].soundsAttack[2] = bark3sound;
98 types[wolftype].soundsAttack[3] = barkgrowlsound;
99 types[wolftype].soundsTalk[0] = growlsound;
100 types[wolftype].soundsTalk[1] = growl2sound;
102 types[wolftype].figureFileName = "Skeleton/BasicFigureWolf";
103 types[wolftype].lowFigureFileName = "Skeleton/BasicFigureWolfLow";
104 types[wolftype].clothesFileName = "Skeleton/RabbitBelt";
105 types[wolftype].modelFileNames[0] = "Models/Wolf.solid";
106 types[wolftype].modelFileNames[1] = "Models/Wolf2.solid";
107 types[wolftype].modelFileNames[2] = "Models/Wolf3.solid";
108 types[wolftype].modelFileNames[3] = "Models/Wolf4.solid";
109 types[wolftype].modelFileNames[4] = "Models/Wolf5.solid";
110 types[wolftype].modelFileNames[5] = "Models/Wolf6.solid";
111 types[wolftype].modelFileNames[6] = "Models/Wolf7.solid";
112 types[wolftype].lowModelFileName = "Models/WolfLow.solid";
113 types[wolftype].modelClothesFileName = "Models/Belt.solid";
115 types[wolftype].skins.resize(3);
116 types[wolftype].skins[0] = "Textures/Wolf.jpg";
117 types[wolftype].skins[1] = "Textures/DarkWolf.jpg";
118 types[wolftype].skins[2] = "Textures/SnowWolf.jpg";
121 types[rabbittype].proportions[0] = 1.2;
122 types[rabbittype].proportions[1] = 1.05;
123 types[rabbittype].proportions[2] = 1;
124 types[rabbittype].proportions[3] = 1.1;
125 types[rabbittype].proportions[3].y = 1.05;
127 types[rabbittype].animRun = runanim;
128 types[rabbittype].animRunning = rabbitrunninganim;
129 types[rabbittype].animCrouch = crouchanim;
130 types[rabbittype].animStop = stopanim;
131 types[rabbittype].animLanding = landanim;
132 types[rabbittype].animLandingHard = landhardanim;
134 types[rabbittype].soundsAttack[0] = rabbitattacksound;
135 types[rabbittype].soundsAttack[1] = rabbitattack2sound;
136 types[rabbittype].soundsAttack[2] = rabbitattack3sound;
137 types[rabbittype].soundsAttack[3] = rabbitattack4sound;
138 types[rabbittype].soundsTalk[0] = rabbitchitter;
139 types[rabbittype].soundsTalk[1] = rabbitchitter2;
141 types[rabbittype].figureFileName = "Skeleton/BasicFigure";
142 types[rabbittype].lowFigureFileName = "Skeleton/BasicFigureLow";
143 types[rabbittype].clothesFileName = "Skeleton/RabbitBelt";
144 types[rabbittype].modelFileNames[0] = "Models/Body.solid";
145 types[rabbittype].modelFileNames[1] = "Models/Body2.solid";
146 types[rabbittype].modelFileNames[2] = "Models/Body3.solid";
147 types[rabbittype].modelFileNames[3] = "Models/Body4.solid";
148 types[rabbittype].modelFileNames[4] = "Models/Body5.solid";
149 types[rabbittype].modelFileNames[5] = "Models/Body6.solid";
150 types[rabbittype].modelFileNames[6] = "Models/Body7.solid";
151 types[rabbittype].lowModelFileName = "Models/BodyLow.solid";
152 types[rabbittype].modelClothesFileName = "Models/Belt.solid";
154 types[rabbittype].skins.resize(10);
155 types[rabbittype].skins[0] = "Textures/Fur3.jpg";
156 types[rabbittype].skins[1] = "Textures/Fur.jpg";
157 types[rabbittype].skins[2] = "Textures/Fur2.jpg";
158 types[rabbittype].skins[3] = "Textures/Lynx.jpg";
159 types[rabbittype].skins[4] = "Textures/Otter.jpg";
160 types[rabbittype].skins[5] = "Textures/Opal.jpg";
161 types[rabbittype].skins[6] = "Textures/Sable.jpg";
162 types[rabbittype].skins[7] = "Textures/Chocolate.jpg";
163 types[rabbittype].skins[8] = "Textures/BW2.jpg";
164 types[rabbittype].skins[9] = "Textures/WB2.jpg";
170 , animCurrent(bounceidleanim)
171 , animTarget(bounceidleanim)
178 , howactive(typeactive)
180 , superruntoggle(false)
214 , rabbitkickenabled(false)
228 , superpermanentdamage(0)
271 , normalsupdatedelay(0)
275 , forwardkeydown(false)
276 , forwardstogglekeydown(false)
277 , rightkeydown(false)
281 , jumptogglekeydown(false)
282 , crouchkeydown(false)
283 , crouchtogglekeydown(false)
285 , drawtogglekeydown(false)
286 , throwkeydown(false)
287 , throwtogglekeydown(false)
288 , attackkeydown(false)
310 , whichdirection(false)
311 , whichdirectiondelay(0)
312 , avoidsomething(false)
322 , lefthandmorphness(0)
323 , righthandmorphness(0)
327 , targetlefthandmorphness(0)
328 , targetrighthandmorphness(0)
329 , targetheadmorphness(1)
330 , targetchestmorphness(0)
331 , targettailmorphness(0)
332 , lefthandmorphstart(0)
333 , lefthandmorphend(0)
334 , righthandmorphstart(0)
335 , righthandmorphend(0)
345 , highreversaldelay(0)
346 , lowreversaldelay(0)
395 , weaponstuckwhere(0)
408 , finalpathfindpoint(0)
409 , targetpathfindpoint(0)
410 , lastpathfindpoint(0)
411 , lastpathfindpoint2(0)
412 , lastpathfindpoint3(0)
413 , lastpathfindpoint4(0)
433 , neckspurtparticledelay(0)
438 , rabbitkickragdoll(false)
446 setProportions(1, 1, 1, 1);
449 /* Read a person in tfile. Throws an error if it’s not valid */
450 Person::Person(FILE* tfile, int mapvers, unsigned i)
454 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
456 funpackf(tfile, "Bi", &howactive);
458 howactive = typeactive;
461 funpackf(tfile, "Bf", &scale);
466 funpackf(tfile, "Bb", &immobile);
471 funpackf(tfile, "Bf", &yaw);
476 if (num_weapons < 0 || num_weapons > 5) {
477 throw InvalidPersonException();
479 if (num_weapons > 0 && num_weapons < 5) {
480 for (int j = 0; j < num_weapons; j++) {
481 weaponids[j] = weapons.size();
483 funpackf(tfile, "Bi", &type);
484 weapons.push_back(Weapon(type, id));
487 funpackf(tfile, "Bi", &numwaypoints);
488 for (int j = 0; j < numwaypoints; j++) {
489 funpackf(tfile, "Bf", &waypoints[j].x);
490 funpackf(tfile, "Bf", &waypoints[j].y);
491 funpackf(tfile, "Bf", &waypoints[j].z);
493 funpackf(tfile, "Bi", &waypointtype[j]);
495 waypointtype[j] = wpkeepwalking;
499 funpackf(tfile, "Bi", &waypoint);
500 if (waypoint > (numwaypoints - 1)) {
504 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
505 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
506 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
507 funpackf(tfile, "Bf Bf", &power, &speedmult);
510 funpackf(tfile, "Bf Bf Bf Bf", &proportions[0], &proportions[1], &proportions[2], &proportions[3]);
512 setProportions(1, 1, 1, 1);
515 funpackf(tfile, "Bi", &numclothes);
516 for (int k = 0; k < numclothes; k++) {
518 funpackf(tfile, "Bi", &templength);
519 for (int l = 0; l < templength; l++) {
520 funpackf(tfile, "Bb", &clothes[k][l]);
522 clothes[k][templength] = '\0';
523 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
529 if (creature == wolftype) {
531 damagetolerance = 300;
538 realoldcoords = coords;
541 void Person::skeletonLoad(bool clothes)
545 PersonType::types[creature].figureFileName,
546 PersonType::types[creature].lowFigureFileName,
547 PersonType::types[creature].clothesFileName,
548 PersonType::types[creature].modelFileNames[0],
549 PersonType::types[creature].modelFileNames[1],
550 PersonType::types[creature].modelFileNames[2],
551 PersonType::types[creature].modelFileNames[3],
552 PersonType::types[creature].modelFileNames[4],
553 PersonType::types[creature].modelFileNames[5],
554 PersonType::types[creature].modelFileNames[6],
555 PersonType::types[creature].lowModelFileName,
556 PersonType::types[creature].modelClothesFileName,
559 skeleton.drawmodel.textureptr.load(PersonType::types[creature].skins[whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
562 void Person::setProportions(float head, float body, float arms, float legs)
564 proportions[0] = head;
565 proportions[1] = body;
566 proportions[2] = arms;
567 proportions[3] = legs;
570 XYZ Person::getProportion(int part) const
572 XYZ prop = PersonType::types[creature].proportions[part] * proportions[part];
582 * GameTick/doPlayerCollisions
584 void Person::CheckKick()
586 if (!(hasvictim && (animTarget == rabbitkickanim && victim && victim != this->shared_from_this() && frameCurrent >= 2 && animCurrent == rabbitkickanim) && distsq(&coords, &victim->coords) < 1.2 && !victim->skeleton.free)) {
590 if (Animation::animations[victim->animTarget].height != lowheight) {
591 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
592 XYZ relative = velocity;
594 Normalise(&relative);
598 if (!Tutorial::active) {
599 emit_sound_at(heavyimpactsound, victim->coords);
602 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
603 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
606 victim->DoDamage(100 * damagemult / victim->protectionhigh);
613 animTarget = backflipanim;
615 velocity = facing * -10;
619 resume_stream(whooshsound);
622 award_bonus(id, cannon);
623 } else if (victim->isCrouch()) {
624 animTarget = rabbitkickreversedanim;
625 animCurrent = rabbitkickreversedanim;
626 victim->animCurrent = rabbitkickreversalanim;
627 victim->animTarget = rabbitkickreversalanim;
633 victim->oldcoords = victim->coords;
634 coords = victim->coords;
635 victim->targetyaw = targetyaw;
636 victim->victim = this->shared_from_this();
643 * GameTick::doPlayerCollisions - spread fire between players
644 * GameTick::ProcessDevKeys - press f to ignite
645 * Person::DoStuff - spread fire from lit campfires and bushes
647 void Person::CatchFire()
649 XYZ flatfacing, flatvelocity;
651 for (int i = 0; i < 10; i++) {
652 howmany = fabs(Random() % (skeleton.joints.size()));
654 flatvelocity = skeleton.joints[howmany].velocity;
655 flatfacing = skeleton.joints[howmany].position * scale + coords;
657 flatvelocity = velocity;
658 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
660 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
665 emit_sound_at(firestartsound, coords);
667 emit_stream_at(stream_firesound, coords);
675 * idle animation for this creature (depending on status)
677 int Person::getIdle()
679 if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype)) {
682 if (hasvictim && (victim != this->shared_from_this())) {
683 if ((!victim->dead && victim->aitype != passivetype &&
684 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
685 victim->id < Person::players.size())) {
686 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
687 if (creature == rabbittype) {
688 return fightidleanim;
690 if (creature == wolftype) {
694 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
695 if (weapons[weaponids[weaponactive]].getType() == knife) {
696 return knifefightidleanim;
698 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1) {
699 return swordfightidlebothanim;
701 if (weapons[weaponids[weaponactive]].getType() == sword) {
702 return swordfightidleanim;
704 if (weapons[weaponids[weaponactive]].getType() == staff) {
705 return swordfightidleanim;
708 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause) {
709 return fightsidestep;
713 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype) {
716 if (howactive == typesitting) {
719 if (howactive == typesittingwall) {
722 if (howactive == typesleeping) {
725 if (howactive == typedead1) {
728 if (howactive == typedead2) {
731 if (howactive == typedead3) {
734 if (howactive == typedead4) {
737 if (creature == rabbittype) {
738 return bounceidleanim;
740 if (creature == wolftype) {
747 * crouch animation for this creature
749 int Person::getCrouch()
751 return PersonType::types[creature].animCrouch;
755 * running animation for this creature (can be upright or all fours)
759 if (superruntoggle && (weaponactive == -1)) {
760 return PersonType::types[creature].animRunning;
762 return PersonType::types[creature].animRun;
768 int Person::getStop()
770 return PersonType::types[creature].animStop;
775 int Person::getLanding()
777 return PersonType::types[creature].animLanding;
782 int Person::getLandhard()
784 return PersonType::types[creature].animLandingHard;
790 * Person::DoAnimations
793 SolidHitBonus(int playerid)
795 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo) {
796 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
798 award_bonus(playerid, solidhit);
803 * spawns blood effects
805 void Person::DoBlood(float howmuch, int which)
807 // FIXME: should abstract out inputs
808 static int bleedxint, bleedyint;
810 if (bloodtoggle && !Tutorial::active) {
811 if (bleeding <= 0 && spurt) {
813 for (int i = 0; i < 3; i++) {
814 // emit blood particles
817 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
818 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
819 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
820 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
823 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
824 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
825 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
826 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
829 if (Random() % 2 == 0) { // 50% chance
830 for (int i = 0; i < 3; i++) {
831 if (Random() % 2 != 0) {
832 // emit teeth particles
835 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
836 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
839 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
840 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
844 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
846 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
848 Sprite::setLastSpriteSpecial(3); // sets it to teeth
854 // FIXME: manipulating attributes
855 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
858 while (PersonType::types[creature].bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || PersonType::types[creature].bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
859 bleedxint = abs(Random() % 512);
860 bleedyint = abs(Random() % 512);
864 bleedy /= realtexdetail;
865 bleedx /= realtexdetail;
866 direction = abs(Random() % 2) * 2 - 1;
875 * spawns big blood effects and ???
876 * modifies character's skin texture
878 void Person::DoBloodBig(float howmuch, int which)
880 static int bleedxint, bleedyint, i, j;
882 if (howmuch && id == 0) {
886 if (!Tutorial::active || id == 0) {
887 if (aitype != playercontrolled && howmuch > 0) {
891 if (creature == wolftype) {
892 int i = abs(Random() % 2);
894 whichsound = snarlsound;
897 whichsound = snarl2sound;
900 if (creature == rabbittype) {
901 int i = abs(Random() % 2);
903 whichsound = rabbitpainsound;
905 if (i == 1 && howmuch >= 2) {
906 whichsound = rabbitpain1sound;
910 if (whichsound != -1) {
911 emit_sound_at(whichsound, coords);
917 if (id == 0 && howmuch > 0) {
921 if (bloodtoggle && decalstoggle && !Tutorial::active) {
922 if (bleeding <= 0 && spurt) {
924 for (int i = 0; i < 3; i++) {
925 // emit blood particles
926 // FIXME: copypaste from above
929 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
930 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
931 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
932 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
935 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
936 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
937 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
938 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
943 // weird texture manipulation code follows.
944 // looks like this is painting blood onto the character's skin texture
945 // FIXME: surely there's a better way
947 int offsetx = 0, offsety = 0;
949 offsety = Random() % 40;
950 offsetx = abs(Random() % 60);
952 if (which == 190 || which == 185) {
953 offsety = Random() % 40;
954 offsetx = abs(Random() % 100) - 20;
957 offsety = Random() % 10;
958 offsetx = Random() % 10;
961 offsety = Random() % 20;
962 offsetx = Random() % 20;
964 if (which == 220 || which == 215) {
973 for (i = 0; i < 512; i++) {
974 for (j = 0; j < 512; j++) {
975 if (PersonType::types[creature].bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && PersonType::types[creature].bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1003 if (endx > 512 - 1) {
1006 if (endy > 512 - 1) {
1009 if (endx < startx) {
1012 if (endy < starty) {
1016 startx /= realtexdetail;
1017 starty /= realtexdetail;
1018 endx /= realtexdetail;
1019 endy /= realtexdetail;
1021 int texdetailint = realtexdetail;
1023 for (i = startx; i < endx; i++) {
1024 for (j = starty; j < endy; j++) {
1025 if (PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
1026 color = Random() % 85 + 170;
1027 where = i * skeleton.skinsize * 3 + j * 3;
1028 if (skeleton.skinText[where + 0] > color / 2) {
1029 skeleton.skinText[where + 0] = color / 2;
1031 skeleton.skinText[where + 1] = 0;
1032 skeleton.skinText[where + 2] = 0;
1036 skeleton.drawmodel.textureptr.bind();
1041 while (PersonType::types[creature].bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || PersonType::types[creature].bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
1042 bleedxint = abs(Random() % 512);
1043 bleedyint = abs(Random() % 512);
1045 bleedy = bleedxint + offsetx;
1046 bleedx = bleedyint + offsety;
1047 bleedy /= realtexdetail;
1048 bleedx /= realtexdetail;
1055 if (bleedx > skeleton.skinsize - 1) {
1056 bleedx = skeleton.skinsize - 1;
1058 if (bleedy > skeleton.skinsize - 1) {
1059 bleedy = skeleton.skinsize - 1;
1061 direction = abs(Random() % 2) * 2 - 1;
1063 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1064 deathbleeding += bleeding;
1065 bloodloss += bleeding * 3;
1067 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1068 if (abs(Random() % 2) == 0) {
1069 aitype = gethelptype;
1072 aitype = attacktypecutoff;
1082 * similar to DoBloodBig
1084 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
1087 static XYZ bloodvel;
1088 static XYZ startpoint, endpoint, colpoint, movepoint;
1089 static float rotationpoint;
1090 static int whichtri;
1091 static XYZ p1, p2, p3, p0;
1094 float coordsx, coordsy;
1097 if (bloodtoggle && decalstoggle && !Tutorial::active) {
1099 if (!skeleton.free) {
1100 where = DoRotation(where, 0, -yaw, 0);
1104 startpoint.y += 100;
1109 // ray testing for a tri in the character model
1110 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
1111 if (whichtri != -1) {
1112 // low level geometry math
1114 p1 = skeleton.drawmodel.getTriangleVertex(whichtri, 0);
1115 p2 = skeleton.drawmodel.getTriangleVertex(whichtri, 1);
1116 p3 = skeleton.drawmodel.getTriangleVertex(whichtri, 2);
1118 bary.x = distsq(&p0, &p1);
1119 bary.y = distsq(&p0, &p2);
1120 bary.z = distsq(&p0, &p3);
1122 total = bary.x + bary.y + bary.z;
1127 bary.x = 1 - bary.x;
1128 bary.y = 1 - bary.y;
1129 bary.z = 1 - bary.z;
1131 total = bary.x + bary.y + bary.z;
1136 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1137 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1138 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1139 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1140 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1141 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1142 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;
1143 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;
1145 if (bleeding <= 0 && spurt) {
1147 for (int i = 0; i < 3; i++) {
1148 // emit blood particles
1149 // FIXME: more copypaste code
1151 if (skeleton.free) {
1152 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1153 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1154 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1155 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1158 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1159 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1160 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1161 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1166 // texture manipulation follows
1168 int offsetx = 0, offsety = 0;
1169 offsetx = (1 + coordsy) * 512 - 291;
1170 offsety = coordsx * 512 - 437;
1177 for (i = 0; i < 512; i++) {
1178 for (j = 0; j < 512; j++) {
1179 if (PersonType::types[creature].bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && PersonType::types[creature].bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1206 if (endx > 512 - 1) {
1209 if (endy > 512 - 1) {
1212 if (endx < startx) {
1215 if (endy < starty) {
1219 startx /= realtexdetail;
1220 starty /= realtexdetail;
1221 endx /= realtexdetail;
1222 endy /= realtexdetail;
1224 int texdetailint = realtexdetail;
1226 for (i = startx; i < endx; i++) {
1227 for (j = starty; j < endy; j++) {
1228 if (PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
1229 color = Random() % 85 + 170;
1230 where = i * skeleton.skinsize * 3 + j * 3;
1231 if (skeleton.skinText[where + 0] > color / 2) {
1232 skeleton.skinText[where + 0] = color / 2;
1234 skeleton.skinText[where + 1] = 0;
1235 skeleton.skinText[where + 2] = 0;
1236 } else if (PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= 160 + 4 && PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= 160 - 4) {
1237 color = Random() % 85 + 170;
1238 where = i * skeleton.skinsize * 3 + j * 3;
1239 if (skeleton.skinText[where + 0] > color / 2) {
1240 skeleton.skinText[where + 0] = color / 2;
1242 skeleton.skinText[where + 1] = 0;
1243 skeleton.skinText[where + 2] = 0;
1247 skeleton.drawmodel.textureptr.bind();
1250 bleedy = (1 + coordsy) * 512;
1251 bleedx = coordsx * 512;
1252 bleedy /= realtexdetail;
1253 bleedx /= realtexdetail;
1260 if (bleedx > skeleton.skinsize - 1) {
1261 bleedx = skeleton.skinsize - 1;
1263 if (bleedy > skeleton.skinsize - 1) {
1264 bleedy = skeleton.skinsize - 1;
1266 direction = abs(Random() % 2) * 2 - 1;
1268 if (whichtri == -1) {
1272 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1273 deathbleeding += bleeding;
1274 bloodloss += bleeding * 3;
1276 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1277 if (abs(Random() % 2) == 0) {
1278 aitype = gethelptype;
1281 aitype = attacktypecutoff;
1292 * guessing this performs a reversal
1294 void Person::Reverse()
1296 if (!((victim->aitype == playercontrolled || hostiletime > 1 || staggerdelay <= 0) && victim->animTarget != jumpupanim && victim->animTarget != jumpdownanim && (!Tutorial::active || cananger) && hostile)) {
1300 if (normaldotproduct(victim->facing, victim->coords - coords) > 0 && (victim->id != 0 || difficulty >= 2) && (creature != wolftype || victim->creature == wolftype)) {
1304 if (animTarget == sweepanim) {
1305 animTarget = sweepreversedanim;
1306 animCurrent = sweepreversedanim;
1307 victim->animCurrent = sweepreversalanim;
1308 victim->animTarget = sweepreversalanim;
1310 if (animTarget == spinkickanim) {
1311 animTarget = spinkickreversedanim;
1312 animCurrent = spinkickreversedanim;
1313 victim->animCurrent = spinkickreversalanim;
1314 victim->animTarget = spinkickreversalanim;
1316 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1317 if (animTarget == rabbittacklinganim) {
1320 victim->frameCurrent = 6;
1321 victim->frameTarget = 7;
1323 animTarget = upunchreversedanim;
1324 animCurrent = upunchreversedanim;
1325 victim->animCurrent = upunchreversalanim;
1326 victim->animTarget = upunchreversalanim;
1328 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1329 if (victim->weaponactive != -1) {
1330 victim->throwtogglekeydown = 1;
1331 XYZ tempVelocity = victim->velocity * .2;
1332 if (tempVelocity.x == 0) {
1333 tempVelocity.x = .1;
1335 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1336 victim->num_weapons--;
1337 if (victim->num_weapons) {
1338 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1339 if (victim->weaponstuck == victim->num_weapons) {
1340 victim->weaponstuck = 0;
1344 victim->weaponactive = -1;
1345 for (unsigned j = 0; j < Person::players.size(); j++) {
1346 Person::players[j]->wentforweapon = 0;
1350 animTarget = staffhitreversedanim;
1351 animCurrent = staffhitreversedanim;
1352 victim->animCurrent = staffhitreversalanim;
1353 victim->animTarget = staffhitreversalanim;
1355 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1356 if (victim->weaponactive != -1) {
1357 victim->throwtogglekeydown = 1;
1358 XYZ tempVelocity = victim->velocity * .2;
1359 if (tempVelocity.x == 0) {
1360 tempVelocity.x = .1;
1362 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1363 victim->num_weapons--;
1364 if (victim->num_weapons) {
1365 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1366 if (victim->weaponstuck == victim->num_weapons) {
1367 victim->weaponstuck = 0;
1371 victim->weaponactive = -1;
1372 for (unsigned j = 0; j < Person::players.size(); j++) {
1373 Person::players[j]->wentforweapon = 0;
1376 animTarget = staffspinhitreversedanim;
1377 animCurrent = staffspinhitreversedanim;
1378 victim->animCurrent = staffspinhitreversalanim;
1379 victim->animTarget = staffspinhitreversalanim;
1381 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1382 if (victim->weaponactive != -1) {
1383 victim->throwtogglekeydown = 1;
1384 XYZ tempVelocity = victim->velocity * .2;
1385 if (tempVelocity.x == 0) {
1386 tempVelocity.x = .1;
1388 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1389 victim->num_weapons--;
1390 if (victim->num_weapons) {
1391 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1392 if (victim->weaponstuck == victim->num_weapons) {
1393 victim->weaponstuck = 0;
1397 victim->weaponactive = -1;
1398 for (unsigned j = 0; j < Person::players.size(); j++) {
1399 Person::players[j]->wentforweapon = 0;
1402 animTarget = swordslashreversedanim;
1403 animCurrent = swordslashreversedanim;
1404 victim->animCurrent = swordslashreversalanim;
1405 victim->animTarget = swordslashreversalanim;
1407 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1408 if (victim->weaponactive != -1) {
1409 victim->throwtogglekeydown = 1;
1410 XYZ tempVelocity = victim->velocity * .2;
1411 if (tempVelocity.x == 0) {
1412 tempVelocity.x = .1;
1414 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1415 victim->num_weapons--;
1416 if (victim->num_weapons) {
1417 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1418 if (victim->weaponstuck == victim->num_weapons) {
1419 victim->weaponstuck = 0;
1423 victim->weaponactive = -1;
1424 for (unsigned j = 0; j < Person::players.size(); j++) {
1425 Person::players[j]->wentforweapon = 0;
1428 animTarget = knifeslashreversedanim;
1429 animCurrent = knifeslashreversedanim;
1430 victim->animCurrent = knifeslashreversalanim;
1431 victim->animTarget = knifeslashreversalanim;
1433 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1434 victim->targettilt2 = targettilt2;
1435 victim->frameCurrent = frameCurrent;
1436 victim->frameTarget = frameTarget;
1437 victim->target = target;
1438 victim->velocity = 0;
1439 victim->oldcoords = victim->coords;
1440 victim->coords = coords;
1441 victim->targetyaw = targetyaw;
1442 victim->yaw = targetyaw;
1443 victim->victim = this->shared_from_this();
1445 if (animTarget == winduppunchanim) {
1446 animTarget = winduppunchblockedanim;
1447 victim->animTarget = blockhighleftanim;
1448 victim->frameTarget = 1;
1449 victim->target = .5;
1450 victim->victim = this->shared_from_this();
1451 victim->targetyaw = targetyaw + 180;
1453 if (animTarget == wolfslapanim) {
1454 animTarget = winduppunchblockedanim;
1455 victim->animTarget = blockhighleftanim;
1456 victim->frameTarget = 1;
1457 victim->target = .5;
1458 victim->victim = this->shared_from_this();
1459 victim->targetyaw = targetyaw + 180;
1461 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1462 animTarget = swordslashparriedanim;
1463 parriedrecently = .4;
1464 victim->parriedrecently = 0;
1465 victim->animTarget = swordslashparryanim;
1466 victim->frameTarget = 1;
1467 victim->target = .5;
1468 victim->victim = this->shared_from_this();
1469 victim->targetyaw = targetyaw + 180;
1471 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1472 if (victim->weaponactive != -1) {
1473 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1474 if (weapons[victim->weaponids[0]].getType() == staff) {
1475 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1477 if (weapons[weaponids[0]].getType() == staff) {
1478 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1480 emit_sound_at(swordstaffsound, victim->coords);
1482 emit_sound_at(metalhitsound, victim->coords);
1486 victim->Puff(righthand);
1488 victim->frameTarget = 0;
1489 victim->animTarget = staggerbackhighanim;
1490 victim->targetyaw = targetyaw + 180;
1492 aim = DoRotation(facing, 0, 90, 0) * 21;
1494 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1495 victim->num_weapons--;
1496 if (victim->num_weapons) {
1497 victim->weaponids[0] = victim->weaponids[num_weapons];
1498 if (victim->weaponstuck == victim->num_weapons) {
1499 victim->weaponstuck = 0;
1502 victim->weaponactive = -1;
1503 for (unsigned i = 0; i < Person::players.size(); i++) {
1504 Person::players[i]->wentforweapon = 0;
1508 if (abs(Random() % 20) == 0) {
1509 if (weaponactive != -1) {
1510 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1511 if (weapons[victim->weaponids[0]].getType() == staff) {
1512 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1514 if (weapons[weaponids[0]].getType() == staff) {
1515 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1518 emit_sound_at(swordstaffsound, coords);
1520 emit_sound_at(metalhitsound, coords);
1528 animTarget = staggerbackhighanim;
1529 targetyaw = targetyaw + 180;
1531 aim = DoRotation(facing, 0, 90, 0) * 21;
1533 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1536 weaponids[0] = weaponids[num_weapons];
1537 if (weaponstuck == num_weapons) {
1542 for (unsigned i = 0; i < Person::players.size(); i++) {
1543 Person::players[i]->wentforweapon = 0;
1548 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1549 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1550 victim->animTarget = dodgebackanim;
1551 victim->frameTarget = 0;
1555 rotatetarget = coords - victim->coords;
1556 Normalise(&rotatetarget);
1557 victim->targetyaw = -asin(0 - rotatetarget.x);
1558 victim->targetyaw *= 360 / 6.28;
1559 if (rotatetarget.z < 0) {
1560 victim->targetyaw = 180 - victim->targetyaw;
1563 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1565 victim->lastattack3 = victim->lastattack2;
1566 victim->lastattack2 = victim->lastattack;
1567 victim->lastattack = victim->animTarget;
1569 victim->animTarget = sweepanim;
1570 victim->frameTarget = 0;
1574 rotatetarget = coords - victim->coords;
1575 Normalise(&rotatetarget);
1576 victim->targetyaw = -asin(0 - rotatetarget.x);
1577 victim->targetyaw *= 360 / 6.28;
1578 if (rotatetarget.z < 0) {
1579 victim->targetyaw = 180 - victim->targetyaw;
1582 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1584 victim->lastattack3 = victim->lastattack2;
1585 victim->lastattack2 = victim->lastattack;
1586 victim->lastattack = victim->animTarget;
1592 victim->velocity = 0;
1594 if (aitype != playercontrolled) {
1596 if (escapednum < 2) {
1597 int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
1598 if ((Random() % chances) == 0) {
1604 if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal) {
1612 void Person::DoDamage(float howmuch)
1616 damagetaken += howmuch / power;
1618 damagedealt += howmuch / power;
1622 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo)) {
1627 if (!Tutorial::active) {
1628 damage += howmuch / power;
1629 permanentdamage += howmuch / 2 / power;
1630 superpermanentdamage += howmuch / 4 / power;
1633 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2) {
1636 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt) {
1641 camerashake += howmuch / 100;
1642 if ((howmuch > 50 && damage > damagetolerance / 2)) {
1643 blackout = damage / damagetolerance;
1651 if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile)) {
1652 aitype = attacktypecutoff;
1654 if (!Tutorial::active && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1655 if (abs(Random() % 2) == 0) {
1656 aitype = gethelptype;
1659 aitype = attacktypecutoff;
1664 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1667 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1668 if (skeleton.free) {
1669 flatvelocity2 = skeleton.joints[i].velocity;
1670 flatfacing2 = skeleton.joints[i].position * scale + coords;
1672 flatvelocity2 = velocity;
1673 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1675 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1676 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1677 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1678 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1679 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1680 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1683 emit_sound_at(splattersound, coords);
1688 if (!dead && creature == wolftype) {
1689 award_bonus(0, Wolfbonus);
1696 if (!Tutorial::active || id == 0) {
1697 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1698 int whichsound = -1;
1700 if (creature == wolftype) {
1701 int i = abs(Random() % 2);
1703 whichsound = snarlsound;
1706 whichsound = snarl2sound;
1709 if (creature == rabbittype) {
1710 int i = abs(Random() % 2);
1712 whichsound = rabbitpainsound;
1714 if (i == 1 && damage > damagetolerance) {
1715 whichsound = rabbitpain1sound;
1719 if (whichsound != -1) {
1720 emit_sound_at(whichsound, coords);
1721 addEnvSound(coords);
1729 * calculate/animate head facing direction?
1731 void Person::DoHead()
1733 static XYZ rotatearound;
1735 static float lookspeed = 500;
1737 if (!freeze && !winfreeze) {
1740 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1741 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1743 while (targetheadyaw > 180) {
1744 targetheadyaw -= 360;
1746 while (targetheadyaw < -180) {
1747 targetheadyaw += 360;
1750 if (targetheadyaw > 160) {
1751 targetheadpitch = targetheadpitch * -1;
1753 if (targetheadyaw < -160) {
1754 targetheadpitch = targetheadpitch * -1;
1756 if (targetheadyaw > 160) {
1757 targetheadyaw = targetheadyaw - 180;
1759 if (targetheadyaw < -160) {
1760 targetheadyaw = targetheadyaw + 180;
1763 if (targetheadpitch > 120) {
1764 targetheadpitch = 120;
1766 if (targetheadpitch < -120) {
1767 targetheadpitch = -120;
1769 if (targetheadyaw > 120) {
1770 targetheadyaw = 120;
1772 if (targetheadyaw < -120) {
1773 targetheadyaw = -120;
1777 targetheadpitch = 0;
1780 if (targetheadyaw > 80) {
1783 if (targetheadyaw < -80) {
1784 targetheadyaw = -80;
1786 if (targetheadpitch > 50) {
1787 targetheadpitch = 50;
1789 if (targetheadpitch < -50) {
1790 targetheadpitch = -50;
1794 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed) {
1795 headyaw = targetheadyaw;
1796 } else if (headyaw > targetheadyaw) {
1797 headyaw -= multiplier * lookspeed;
1798 } else if (headyaw < targetheadyaw) {
1799 headyaw += multiplier * lookspeed;
1802 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2) {
1803 headpitch = targetheadpitch;
1804 } else if (headpitch > targetheadpitch) {
1805 headpitch -= multiplier * lookspeed / 2;
1806 } else if (headpitch < targetheadpitch) {
1807 headpitch += multiplier * lookspeed / 2;
1810 rotatearound = jointPos(neck);
1811 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1815 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1816 facing = DoRotation(facing, headpitch * .4, 0, 0);
1817 facing = DoRotation(facing, 0, headyaw * .4, 0);
1820 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1821 facing = DoRotation(facing, headpitch * .8, 0, 0);
1822 facing = DoRotation(facing, 0, headyaw * .8, 0);
1825 if (animTarget == walkanim) {
1826 facing = DoRotation(facing, headpitch * .6, 0, 0);
1827 facing = DoRotation(facing, 0, headyaw * .6, 0);
1830 skeleton.specialforward[0] = facing;
1831 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1832 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
1833 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1834 skeleton.FindRotationMuscle(i, animTarget);
1841 * ragdolls character?
1843 void Person::RagDoll(bool checkcollision)
1848 if (!skeleton.free) {
1852 if (id == 0 && isFlip()) {
1860 facing = DoRotation(facing, 0, yaw, 0);
1862 skeleton.freetime = 0;
1864 skeleton.longdead = 0;
1867 skeleton.broken = 0;
1868 skeleton.spinny = 1;
1870 skeleton.freefall = 1;
1872 if (!isnormal(velocity.x)) {
1875 if (!isnormal(velocity.y)) {
1878 if (!isnormal(velocity.z)) {
1881 if (!isnormal(yaw)) {
1884 if (!isnormal(coords.x)) {
1887 if (!isnormal(tilt)) {
1890 if (!isnormal(tilt2)) {
1894 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1895 skeleton.joints[i].delay = 0;
1896 skeleton.joints[i].locked = 0;
1897 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1898 if (!isnormal(skeleton.joints[i].position.x)) {
1899 skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1901 if (!isnormal(skeleton.joints[i].position.x)) {
1902 skeleton.joints[i].position = coords;
1904 skeleton.joints[i].position.y += .1;
1905 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1906 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1909 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1910 skeleton.joints[i].velocity = 0;
1911 skeleton.joints[i].velchange = 0;
1913 skeleton.DoConstraints(&coords, &scale);
1914 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
1915 skeleton.DoConstraints(&coords, &scale);
1916 skeleton.DoConstraints(&coords, &scale);
1917 skeleton.DoConstraints(&coords, &scale);
1918 skeleton.DoConstraints(&coords, &scale);
1921 speed = targetFrame().speed * 2;
1922 if (currentFrame().speed > targetFrame().speed) {
1923 speed = currentFrame().speed * 2;
1926 speed = transspeed * 2;
1931 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1932 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height) {
1933 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);
1935 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1937 change.x = (float)(Random() % 100) / 100;
1938 change.y = (float)(Random() % 100) / 100;
1939 change.z = (float)(Random() % 100) / 100;
1940 skeleton.joints[i].velocity += change;
1941 skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change;
1943 change.x = (float)(Random() % 100) / 100;
1944 change.y = (float)(Random() % 100) / 100;
1945 change.z = (float)(Random() % 100) / 100;
1946 skeleton.joints[i].velchange += change;
1947 skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change;
1950 if (checkcollision) {
1953 if (!skeleton.joints.empty()) {
1956 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1957 average += skeleton.joints[j].position;
1959 average /= skeleton.joints.size();
1960 coords += average * scale;
1961 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1962 skeleton.joints[j].position -= average;
1966 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1967 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1968 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
1969 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1972 if (SphereCheck(&lowpoint, 3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
1973 coords.x = lowpoint.x;
1974 coords.z = lowpoint.z;
1983 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1984 velocity += skeleton.joints[i].velocity * scale;
1986 velocity /= skeleton.joints.size();
1989 if (Random() % 2 == 0) {
1990 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1991 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1992 weapons[weaponids[0]].velocity.x += .01;
1995 weaponids[0] = weaponids[num_weapons];
1996 if (weaponstuck == num_weapons) {
2001 for (unsigned i = 0; i < Person::players.size(); i++) {
2002 Person::players[i]->wentforweapon = 0;
2007 animTarget = bounceidleanim;
2008 animCurrent = bounceidleanim;
2016 void Person::FootLand(bodypart whichfoot, float opacity)
2018 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
2019 cerr << "FootLand called on wrong bodypart" << endl;
2022 static XYZ terrainlight;
2023 static XYZ footvel, footpoint;
2024 if (opacity >= 1 || skiddelay <= 0) {
2027 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2028 if (distsq(&footpoint, &viewer)) {
2029 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
2031 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
2032 footvel = velocity / 5;
2033 if (footvel.y < .8) {
2036 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2037 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
2038 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
2039 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
2040 if (environment == snowyenvironment) {
2041 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
2043 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
2045 } else if (environment == grassyenvironment) {
2046 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
2047 } else if (environment == desertenvironment) {
2048 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
2050 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
2054 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
2055 footvel = velocity / 5;
2056 if (footvel.y < .8) {
2059 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2060 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
2061 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
2068 * make a puff effect at a body part (dust effect?)
2070 void Person::Puff(int whichlabel)
2072 static XYZ footvel, footpoint;
2075 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
2076 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
2080 * I think I added this in an attempt to clean up code
2082 void Person::setTargetAnimation(int animation)
2084 animTarget = animation;
2093 void Person::DoAnimations()
2095 if (!skeleton.free) {
2096 static float oldtarget;
2098 if (isIdle() && animCurrent != getIdle()) {
2099 normalsupdatedelay = 0;
2102 if (animTarget == tempanim || animCurrent == tempanim) {
2103 Animation::animations[tempanim] = tempanimation;
2105 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
2112 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
2113 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
2115 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z)) {
2118 if (!crouchkeydown && velocity.y >= -15) {
2122 if ((animCurrent == jumpupanim || animTarget == jumpdownanim) /*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
2127 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
2129 if (normaldotproduct(targfacing, velocity) >= -.3) {
2130 animTarget = flipanim;
2132 animTarget = backflipanim;
2134 crouchtogglekeydown = 1;
2143 if (Animation::animations[animTarget].attack != reversed) {
2146 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
2147 crouchtogglekeydown = 0;
2148 if (aitype == playercontrolled) {
2152 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain)) {
2156 crouchtogglekeydown = 1;
2160 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
2162 normalsupdatedelay = 0;
2167 if (animTarget == rollanim && frameTarget == 3 && onfire) {
2169 emit_sound_at(fireendsound, coords);
2170 pause_sound(stream_firesound);
2174 if (animTarget == rabbittacklinganim && frameTarget == 1) {
2175 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0) {
2178 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
2179 if (normaldotproduct(victim->facing, facing) > 0) {
2180 victim->animTarget = rabbittackledbackanim;
2182 victim->animTarget = rabbittackledfrontanim;
2184 victim->frameTarget = 2;
2187 victim->targetyaw = yaw;
2188 if (victim->aitype == gethelptype) {
2189 victim->DoDamage(victim->damagetolerance - victim->damage);
2191 //victim->DoDamage(30);
2192 if (creature == wolftype) {
2194 emit_sound_at(clawslicesound, victim->coords);
2196 victim->DoBloodBig(1 / victim->armorhead, 210);
2198 award_bonus(id, TackleBonus,
2199 victim->aitype == gethelptype ? 50 : 0);
2203 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2204 if (weapons[weaponids[0]].getType() == knife) {
2205 if (weaponactive == -1) {
2207 } else if (weaponactive == 0) {
2211 if (weaponactive == -1) {
2212 emit_sound_at(knifesheathesound, coords);
2214 if (weaponactive != -1) {
2215 emit_sound_at(knifedrawsound, coords, 128);
2218 drawtogglekeydown = 1;
2221 if (!Tutorial::active || id == 0) {
2222 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2223 int whichsound = -1;
2225 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2226 if (targetFrame().label == 1) {
2227 whichsound = footstepsound;
2229 whichsound = footstepsound2;
2231 if (targetFrame().label == 1) {
2232 FootLand(leftfoot, 1);
2234 if (targetFrame().label == 2) {
2235 FootLand(rightfoot, 1);
2237 if (targetFrame().label == 3 && isRun()) {
2238 FootLand(rightfoot, 1);
2239 FootLand(leftfoot, 1);
2242 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2243 if (targetFrame().label == 1) {
2244 whichsound = footstepsound3;
2246 whichsound = footstepsound4;
2251 if (targetFrame().label == 1) {
2252 whichsound = footstepsound3;
2254 whichsound = footstepsound4;
2257 if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2258 if (Animation::animations[animTarget].attack != neutral) {
2259 unsigned r = abs(Random() % 3);
2261 whichsound = lowwhooshsound;
2264 whichsound = midwhooshsound;
2267 whichsound = highwhooshsound;
2270 if (Animation::animations[animTarget].attack == neutral) {
2271 whichsound = movewhooshsound;
2273 } else if (targetFrame().label == 4) {
2274 whichsound = knifeswishsound;
2276 if (targetFrame().label == 8 && !Tutorial::active) {
2277 whichsound = landsound2;
2280 if (whichsound != -1) {
2281 emit_sound_at(whichsound, coords, 256.);
2284 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2285 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2286 addEnvSound(coords, 15);
2288 addEnvSound(coords, 6);
2293 if (targetFrame().label == 3) {
2295 emit_sound_at(whichsound, coords, 128.);
2302 if (!Tutorial::active || id == 0) {
2303 if (speechdelay <= 0) {
2304 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
2305 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2306 int whichsound = -1;
2307 if (targetFrame().label == 4 && aitype != playercontrolled) {
2308 if (Animation::animations[animTarget].attack != neutral) {
2309 unsigned r = abs(Random() % 4);
2310 whichsound = PersonType::types[creature].soundsAttack[r];
2315 if (whichsound != -1) {
2316 emit_sound_at(whichsound, coords);
2323 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2324 FootLand(leftfoot, 1);
2325 FootLand(rightfoot, 1);
2329 currentoffset = targetoffset;
2330 frameTarget = frameCurrent;
2331 animCurrent = animTarget;
2334 if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2335 for (unsigned i = 0; i < weapons.size(); i++) {
2336 if (weapons[i].owner == -1) {
2337 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2338 if (distsq(&coords, &weapons[i].position) >= 1) {
2339 if (weapons[i].getType() != staff) {
2340 emit_sound_at(knifedrawsound, coords, 128.);
2350 if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2351 for (unsigned i = 0; i < weapons.size(); i++) {
2352 bool willwork = true;
2353 if (weapons[i].owner != -1) {
2354 if (Person::players[weapons[i].owner]->weaponstuck != -1) {
2355 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i)) {
2356 if (Person::players[weapons[i].owner]->num_weapons > 1) {
2362 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free)) {
2363 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2364 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2365 bool fleshstuck = false;
2366 if (weapons[i].owner != -1) {
2367 if (victim->weaponstuck != -1) {
2368 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2374 emit_sound_at(fleshstabremovesound, coords, 128.);
2376 if (weapons[i].getType() != staff) {
2377 emit_sound_at(knifedrawsound, coords, 128.);
2380 if (weapons[i].owner != -1) {
2381 victim = Person::players[weapons[i].owner];
2382 if (victim->num_weapons == 1) {
2383 victim->num_weapons = 0;
2385 victim->num_weapons = 1;
2388 //victim->weaponactive=-1;
2389 victim->skeleton.longdead = 0;
2390 victim->skeleton.free = 1;
2391 victim->skeleton.broken = 0;
2393 for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) {
2394 victim->skeleton.joints[j].velchange = 0;
2395 victim->skeleton.joints[j].locked = 0;
2401 Normalise(&relative);
2402 XYZ footvel, footpoint;
2404 footpoint = weapons[i].position;
2405 if (victim->weaponstuck != -1) {
2406 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2408 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2410 weapons[i].bloody = 2;
2411 weapons[i].blooddrip = 5;
2412 victim->weaponstuck = -1;
2415 if (victim->num_weapons > 0) {
2416 if (victim->weaponstuck != 0 && victim->weaponstuck != -1) {
2417 victim->weaponstuck = 0;
2419 if (victim->weaponids[0] == int(i)) {
2420 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2424 victim->jointVel(abdomen) += relative * 6;
2425 victim->jointVel(neck) += relative * 6;
2426 victim->jointVel(rightshoulder) += relative * 6;
2427 victim->jointVel(leftshoulder) += relative * 6;
2436 if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2437 if (weaponactive == -1) {
2439 } else if (weaponactive == 0) {
2441 if (num_weapons == 2) {
2443 buffer = weaponids[0];
2444 weaponids[0] = weaponids[1];
2445 weaponids[1] = buffer;
2448 if (weaponactive == -1) {
2449 emit_sound_at(knifesheathesound, coords, 128.);
2451 if (weaponactive != -1) {
2452 emit_sound_at(knifedrawsound, coords, 128.);
2456 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2457 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2458 Normalise(&rotatetarget);
2459 targetyaw = -asin(0 - rotatetarget.x);
2460 targetyaw *= 360 / 6.28;
2461 if (rotatetarget.z < 0) {
2462 targetyaw = 180 - targetyaw;
2465 if (animTarget == walljumprightkickanim) {
2468 if (animTarget == walljumpleftkickanim) {
2475 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0)) {
2479 if (distsq(&victim->coords, &/*Person::players[i]->*/ coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1) {
2487 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2488 animTarget = rabbittackleanim;
2490 emit_sound_at(jumpsound, coords);
2498 targetloc = velocity;
2499 Normalise(&targetloc);
2500 targetloc += coords;
2501 for (unsigned i = 0; i < Person::players.size(); i++) {
2503 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2504 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2509 if (closestid != -1) {
2510 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2512 victim = Person::players[closestid];
2513 coords = victim->coords;
2514 animCurrent = rabbittacklinganim;
2515 animTarget = rabbittacklinganim;
2519 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2520 rotatetarget = coords - victim->coords;
2521 Normalise(&rotatetarget);
2522 targetyaw = -asin(0 - rotatetarget.x);
2523 targetyaw *= 360 / 6.28;
2524 if (rotatetarget.z < 0) {
2525 targetyaw = 180 - targetyaw;
2528 if (animTarget != rabbitrunninganim) {
2529 emit_sound_at(jumpsound, coords, 128.);
2536 float damagemult = 1 * power;
2537 if (creature == wolftype) {
2538 damagemult = 2.5 * power;
2541 damagemult /= victim->damagetolerance / 200;
2543 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)) {
2544 if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2545 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2550 if (Random() % 2 || creature == wolftype) {
2553 if (creature == wolftype) {
2557 if (!Tutorial::active) {
2558 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2560 if (creature == wolftype) {
2561 emit_sound_at(clawslicesound, victim->coords, 128.);
2563 victim->DoBloodBig(2 / victim->armorhead, 175);
2567 relative = victim->coords - coords;
2569 Normalise(&relative);
2570 relative = DoRotation(relative, 0, -90, 0);
2571 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2572 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2574 victim->jointVel(head) += relative * damagemult * 200;
2576 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2582 if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2583 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2588 if (Random() % 2 || creature == wolftype) {
2590 if (creature == wolftype) {
2594 emit_sound_at(whooshhitsound, victim->coords);
2595 if (creature == wolftype) {
2596 emit_sound_at(clawslicesound, victim->coords, 128.);
2598 victim->DoBloodBig(2, 175);
2602 relative = victim->coords - coords;
2604 Normalise(&relative);
2606 Normalise(&relative);
2607 relative = DoRotation(relative, 0, 90, 0);
2608 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2609 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2611 victim->jointVel(head) += relative * damagemult * 100;
2613 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2617 if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2618 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2625 if (!Tutorial::active) {
2626 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2628 if (creature == wolftype) {
2629 emit_sound_at(clawslicesound, victim->coords, 128.);
2631 victim->DoBloodBig(2 / victim->armorhead, 175);
2637 Normalise(&relative);
2638 relative = DoRotation(relative, 0, -90, 0);
2639 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2640 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2642 victim->jointVel(head) += relative * damagemult * 200;
2644 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2646 if (victim->damage > victim->damagetolerance) {
2647 award_bonus(id, style);
2654 if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2655 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2662 if (!Tutorial::active) {
2663 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2665 if (creature == wolftype) {
2666 emit_sound_at(clawslicesound, victim->coords, 128.);
2668 victim->DoBloodBig(2 / victim->armorhead, 175);
2674 Normalise(&relative);
2675 relative = DoRotation(relative, 0, 90, 0);
2676 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2677 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2679 victim->jointVel(head) += relative * damagemult * 200;
2681 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2683 if (victim->damage > victim->damagetolerance) {
2684 award_bonus(id, style);
2691 if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2692 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2701 emit_sound_at(whooshhitsound, victim->coords);
2704 relative = victim->coords - coords;
2706 Normalise(&relative);
2707 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2708 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2710 victim->jointVel(head) += relative * damagemult * 100;
2712 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2716 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
2717 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2722 emit_sound_at(whooshhitsound, victim->coords, 128.);
2724 victim->skeleton.longdead = 0;
2725 victim->skeleton.free = 1;
2726 victim->skeleton.broken = 0;
2727 victim->skeleton.spinny = 1;
2729 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2730 victim->skeleton.joints[i].velchange = 0;
2731 victim->skeleton.joints[i].delay = 0;
2732 victim->skeleton.joints[i].locked = 0;
2733 //victim->skeleton.joints[i].velocity=0;
2739 Normalise(&relative);
2740 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2741 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2742 victim->skeleton.joints[i].position.y += relative.y * .3;
2743 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2744 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2746 victim->Puff(abdomen);
2747 victim->jointVel(abdomen).y = relative.y * 400;
2751 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2752 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2757 if (!Tutorial::active) {
2758 emit_sound_at(heavyimpactsound, coords, 128.);
2761 relative = victim->coords - coords;
2763 Normalise(&relative);
2764 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2765 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2767 victim->Puff(abdomen);
2768 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2772 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2773 victim->jointVel(abdomen) += relative * damagemult * 300;
2777 if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
2778 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2783 if (!Tutorial::active) {
2784 emit_sound_at(thudsound, coords);
2787 victim->skeleton.longdead = 0;
2788 victim->skeleton.free = 1;
2789 victim->skeleton.broken = 0;
2790 victim->skeleton.spinny = 1;
2792 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2793 victim->skeleton.joints[i].velchange = 0;
2794 //victim->skeleton.joints[i].delay=0;
2795 victim->skeleton.joints[i].locked = 0;
2798 relative = victim->coords - coords;
2799 Normalise(&relative);
2801 Normalise(&relative);
2802 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2803 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2805 if (!victim->dead) {
2809 victim->Puff(abdomen);
2810 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2811 victim->jointVel(abdomen) += relative * damagemult * 200;
2813 if (!victim->dead) {
2819 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2822 if (!victim->skeleton.free) {
2828 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2829 emit_sound_at(knifesheathesound, coords, 128.);
2832 if (victim && hasvictim) {
2833 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2835 XYZ where, startpoint, endpoint, movepoint, colpoint;
2836 float rotationpoint;
2838 if (weapons[weaponids[weaponactive]].getType() == knife) {
2839 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2840 where -= victim->coords;
2841 if (!victim->skeleton.free) {
2842 where = DoRotation(where, 0, -victim->yaw, 0);
2846 startpoint.y += 100;
2850 if (weapons[weaponids[weaponactive]].getType() == sword) {
2851 where = weapons[weaponids[weaponactive]].position;
2852 where -= victim->coords;
2853 if (!victim->skeleton.free) {
2854 where = DoRotation(where, 0, -victim->yaw, 0);
2857 where = weapons[weaponids[weaponactive]].tippoint;
2858 where -= victim->coords;
2859 if (!victim->skeleton.free) {
2860 where = DoRotation(where, 0, -victim->yaw, 0);
2864 if (weapons[weaponids[weaponactive]].getType() == staff) {
2865 where = weapons[weaponids[weaponactive]].position;
2866 where -= victim->coords;
2867 if (!victim->skeleton.free) {
2868 where = DoRotation(where, 0, -victim->yaw, 0);
2871 where = weapons[weaponids[weaponactive]].tippoint;
2872 where -= victim->coords;
2873 if (!victim->skeleton.free) {
2874 where = DoRotation(where, 0, -victim->yaw, 0);
2880 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2882 if (whichtri != -1) {
2883 if (victim->dead != 2) {
2884 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2885 if (!victim->dead) {
2886 award_bonus(id, FinishedBonus);
2890 weapons[weaponids[weaponactive]].bloody = 2;
2893 victim->skeleton.longdead = 0;
2894 victim->skeleton.free = 1;
2895 victim->skeleton.broken = 0;
2897 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2898 victim->skeleton.joints[i].velchange = 0;
2899 victim->skeleton.joints[i].locked = 0;
2900 //victim->skeleton.joints[i].velocity=0;
2902 emit_sound_at(fleshstabsound, coords, 128);
2904 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2905 weapons[weaponids[weaponactive]].blooddrip += 5;
2906 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2908 if (whichtri == -1) {
2910 emit_sound_at(knifesheathesound, coords, 128.);
2916 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
2918 emit_sound_at(knifedrawsound, coords, 128);
2921 if (victim && hasvictim) {
2922 XYZ footvel, footpoint;
2924 emit_sound_at(fleshstabremovesound, coords, 128.);
2927 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2929 if (weapons[weaponids[weaponactive]].getType() == sword) {
2930 XYZ where, startpoint, endpoint, movepoint;
2931 float rotationpoint;
2934 where = weapons[weaponids[weaponactive]].position;
2935 where -= victim->coords;
2936 if (!victim->skeleton.free) {
2937 where = DoRotation(where, 0, -victim->yaw, 0);
2940 where = weapons[weaponids[weaponactive]].tippoint;
2941 where -= victim->coords;
2942 if (!victim->skeleton.free) {
2943 where = DoRotation(where, 0, -victim->yaw, 0);
2949 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2950 footpoint += victim->coords;
2952 if (whichtri == -1) {
2953 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2956 if (weapons[weaponids[weaponactive]].getType() == staff) {
2957 XYZ where, startpoint, endpoint, movepoint;
2958 float rotationpoint;
2961 where = weapons[weaponids[weaponactive]].position;
2962 where -= victim->coords;
2963 if (!victim->skeleton.free) {
2964 where = DoRotation(where, 0, -victim->yaw, 0);
2967 where = weapons[weaponids[weaponactive]].tippoint;
2968 where -= victim->coords;
2969 if (!victim->skeleton.free) {
2970 where = DoRotation(where, 0, -victim->yaw, 0);
2976 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2977 footpoint += victim->coords;
2979 if (whichtri == -1) {
2980 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2983 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2985 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2986 victim->skeleton.longdead = 0;
2987 victim->skeleton.free = 1;
2988 victim->skeleton.broken = 0;
2990 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2991 victim->skeleton.joints[i].velchange = 0;
2992 victim->skeleton.joints[i].locked = 0;
2993 //victim->skeleton.joints[i].velocity=0;
2999 Normalise(&relative);
3000 //victim->Puff(abdomen);
3002 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
3005 if (victim->bloodloss < victim->damagetolerance) {
3006 victim->bloodloss += 1000;
3010 victim->jointVel(abdomen) += relative * damagemult * 20;
3014 if (!hasvictim && onterrain) {
3015 weapons[weaponids[weaponactive]].bloody = 0;
3016 weapons[weaponids[weaponactive]].blooddrip = 0;
3020 if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3021 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
3030 if (!Tutorial::active) {
3031 emit_sound_at(heavyimpactsound, victim->coords, 128);
3036 relative = victim->coords - coords;
3038 Normalise(&relative);
3039 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3040 victim->skeleton.joints[i].velocity = relative * 30;
3042 victim->jointVel(head) += relative * damagemult * 150;
3044 victim->frameTarget = 0;
3045 victim->animTarget = staggerbackhardanim;
3046 victim->targetyaw = targetyaw + 180;
3048 victim->stunned = 1;
3051 victim->Puff(abdomen);
3052 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
3058 if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3059 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
3064 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
3065 if (!Tutorial::active) {
3066 emit_sound_at(thudsound, victim->coords);
3068 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
3069 if (!Tutorial::active) {
3070 emit_sound_at(whooshhitsound, victim->coords);
3073 if (!Tutorial::active) {
3074 emit_sound_at(heavyimpactsound, victim->coords);
3078 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight) {
3082 relative = victim->coords - coords;
3084 Normalise(&relative);
3086 Normalise(&relative);
3087 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3088 victim->skeleton.joints[i].velocity = relative * 5;
3090 victim->jointVel(abdomen) += relative * damagemult * 400;
3092 victim->frameTarget = 0;
3093 victim->animTarget = staggerbackhardanim;
3094 victim->targetyaw = targetyaw + 180;
3096 victim->stunned = 1;
3098 victim->Puff(abdomen);
3099 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
3105 if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3106 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3107 if (victim->id == 0) {
3110 emit_sound_at(landsound2, victim->coords);
3116 if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3117 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3118 if (victim->id == 0) {
3122 if (weaponactive != -1) {
3123 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3124 if (weapons[victim->weaponids[0]].getType() == staff) {
3125 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3127 if (weapons[weaponids[0]].getType() == staff) {
3128 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3131 emit_sound_at(swordstaffsound, victim->coords);
3133 emit_sound_at(metalhitsound, victim->coords);
3141 if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3142 if (weaponactive != -1) {
3145 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);
3147 weapons[weaponids[0]].thrown(aim * 50);
3150 weaponids[0] = weaponids[num_weapons];
3156 if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3158 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 && /*Animation::animations[victim->animTarget].height!=lowheight&&*/ victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
3160 if (!Tutorial::active) {
3161 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
3164 award_bonus(id, Slicebonus);
3165 if (!Tutorial::active) {
3166 emit_sound_at(knifeslicesound, victim->coords);
3168 //victim->jointVel(abdomen)+=relative*damagemult*200;
3169 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
3170 if (victim->id != 0 || difficulty == 2) {
3171 victim->frameTarget = 0;
3172 victim->animTarget = staggerbackhardanim;
3173 victim->targetyaw = targetyaw + 180;
3177 victim->lowreversaldelay = 0;
3178 victim->highreversaldelay = 0;
3179 if (aitype != playercontrolled) {
3180 weaponmissdelay = .6;
3183 if (!Tutorial::active) {
3184 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3185 weapons[weaponids[weaponactive]].bloody = 1;
3187 weapons[weaponids[weaponactive]].blooddrip += 3;
3190 XYZ footvel, footpoint;
3192 if (skeleton.free) {
3193 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3195 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3197 if (Tutorial::active) {
3198 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
3201 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
3203 footvel = DoRotation(facing, 0, 90, 0) * .8;
3204 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3205 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3206 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3207 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3209 victim->DoDamage(damagemult * 0);
3213 if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3214 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
3215 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
3216 award_bonus(id, Slashbonus);
3218 if (!Tutorial::active) {
3219 if (normaldotproduct(victim->facing, victim->coords - coords) < 0) {
3220 victim->DoBloodBig(2 / victim->armorhigh, 190);
3222 victim->DoBloodBig(2 / victim->armorhigh, 185);
3224 victim->deathbleeding = 1;
3225 emit_sound_at(swordslicesound, victim->coords);
3226 victim->frameTarget = 0;
3227 victim->animTarget = staggerbackhardanim;
3228 victim->targetyaw = targetyaw + 180;
3230 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3231 weapons[weaponids[weaponactive]].bloody = 1;
3233 weapons[weaponids[weaponactive]].blooddrip += 3;
3235 float bloodlossamount;
3236 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
3237 victim->bloodloss += bloodlossamount / victim->armorhigh;
3238 victim->DoDamage(damagemult * 0);
3240 XYZ footvel, footpoint;
3242 if (skeleton.free) {
3243 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3245 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3248 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3250 footvel = DoRotation(facing, 0, 90, 0) * .8;
3252 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3253 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3254 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3255 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3258 if (victim->weaponactive != -1) {
3259 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3260 if (weapons[victim->weaponids[0]].getType() == staff) {
3261 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3263 if (weapons[weaponids[0]].getType() == staff) {
3264 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3267 emit_sound_at(swordstaffsound, victim->coords);
3269 emit_sound_at(metalhitsound, victim->coords);
3274 victim->Puff(righthand);
3276 victim->frameTarget = 0;
3277 victim->animTarget = staggerbackhighanim;
3278 victim->targetyaw = targetyaw + 180;
3280 aim = DoRotation(facing, 0, 90, 0) * 21;
3282 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3283 victim->num_weapons--;
3284 if (victim->num_weapons) {
3285 victim->weaponids[0] = victim->weaponids[num_weapons];
3286 if (victim->weaponstuck == victim->num_weapons) {
3287 victim->weaponstuck = 0;
3290 victim->weaponactive = -1;
3291 for (unsigned i = 0; i < Person::players.size(); i++) {
3292 Person::players[i]->wentforweapon = 0;
3298 if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3299 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3300 if (!Tutorial::active) {
3301 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3306 if (Random() % 2 || creature == wolftype) {
3309 emit_sound_at(staffheadsound, victim->coords);
3313 relative = victim->coords - coords;
3315 Normalise(&relative);
3316 relative = DoRotation(relative, 0, 90, 0);
3318 Normalise(&relative);
3319 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3320 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3322 victim->jointVel(head) += relative * damagemult * 230;
3323 victim->jointVel(neck) += relative * damagemult * 230;
3325 if (!Tutorial::active) {
3326 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3328 award_bonus(id, solidhit, 30);
3333 if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3334 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3335 if (!Tutorial::active) {
3336 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3341 if (Random() % 2 || creature == wolftype) {
3344 emit_sound_at(staffheadsound, victim->coords);
3348 relative = victim->coords - coords;
3350 Normalise(&relative);
3351 relative = DoRotation(relative, 0, -90, 0);
3352 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3353 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3355 victim->jointVel(head) += relative * damagemult * 220;
3356 victim->jointVel(neck) += relative * damagemult * 220;
3358 if (!Tutorial::active) {
3359 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3361 award_bonus(id, solidhit, 60);
3366 if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3367 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3369 if (!Tutorial::active) {
3370 if (!victim->dead) {
3371 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3376 if (Random() % 2 || creature == wolftype) {
3379 emit_sound_at(staffbodysound, victim->coords);
3381 victim->skeleton.longdead = 0;
3382 victim->skeleton.free = 1;
3383 victim->skeleton.broken = 0;
3385 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3386 victim->skeleton.joints[i].velchange = 0;
3387 victim->skeleton.joints[i].locked = 0;
3388 //victim->skeleton.joints[i].velocity=0;
3395 Normalise(&relative);
3396 if (!victim->dead) {
3397 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3398 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3400 victim->jointVel(abdomen) += relative * damagemult * 40;
3403 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3404 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3407 victim->Puff(abdomen);
3408 if (!Tutorial::active) {
3409 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3411 if (!victim->dead) {
3412 award_bonus(id, solidhit, 40);
3418 if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3419 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3425 relative = victim->coords - coords;
3427 Normalise(&relative);
3431 if (Animation::animations[victim->animTarget].height == lowheight) {
3437 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3438 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3440 victim->jointVel(head) += relative * damagemult * 200;
3441 if (!Tutorial::active) {
3442 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3445 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3446 if (victim->howactive == typesleeping) {
3447 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3449 if (creature == wolftype) {
3450 emit_sound_at(clawslicesound, victim->coords, 128.);
3452 victim->DoBloodBig(2 / victim->armorhead, 175);
3455 if (victim->damage >= victim->damagetolerance) {
3458 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3459 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3461 victim->jointVel(abdomen) += relative * damagemult * 200;
3462 victim->frameTarget = 0;
3463 victim->animTarget = staggerbackhighanim;
3464 victim->targetyaw = targetyaw + 180;
3466 if (!Tutorial::active) {
3467 emit_sound_at(landsound2, victim->coords, 128.);
3469 victim->Puff(abdomen);
3470 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3471 if (creature == wolftype) {
3472 emit_sound_at(clawslicesound, victim->coords, 128.);
3474 victim->DoBloodBig(2 / victim->armorhigh, 170);
3480 if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3481 if ((victim->animTarget != jumpupanim) &&
3482 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3483 (victim != this->shared_from_this())) {
3488 if (!Tutorial::active) {
3489 emit_sound_at(landsound2, victim->coords, 128.);
3492 relative = victim->coords - coords;
3494 Normalise(&relative);
3496 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3499 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3500 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3502 relative = DoRotation(relative, 0, -90, 0);
3504 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3505 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) {
3506 victim->skeleton.joints[i].velocity = relative * 80;
3509 victim->Puff(rightankle);
3510 victim->Puff(leftankle);
3511 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3513 if (victim->damage >= victim->damagetolerance) {
3516 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3517 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3519 relative = DoRotation(relative, 0, -90, 0);
3520 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3521 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) {
3522 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3525 victim->jointVel(abdomen) += relative * damagemult * 200;
3526 victim->frameTarget = 0;
3527 victim->animTarget = staggerbackhighanim;
3528 victim->targetyaw = targetyaw + 180;
3530 if (!Tutorial::active) {
3531 emit_sound_at(landsound2, victim->coords, 128.);
3533 victim->Puff(abdomen);
3534 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3541 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3542 if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3551 if (!Tutorial::active) {
3552 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3554 if (creature == wolftype) {
3555 emit_sound_at(clawslicesound, victim->coords, 128);
3557 victim->DoBloodBig(2 / victim->armorhigh, 170);
3561 relative = victim->coords - oldcoords;
3563 Normalise(&relative);
3564 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3565 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3567 victim->jointVel(abdomen) += relative * damagemult * 200;
3568 victim->Puff(abdomen);
3569 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3571 award_bonus(id, Reversal);
3574 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3575 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3576 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3577 takeWeapon(victim->weaponids[victim->weaponactive]);
3578 victim->num_weapons--;
3579 if (victim->num_weapons > 0) {
3580 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3582 victim->weaponactive = -1;
3587 if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3596 emit_sound_at(whooshhitsound, victim->coords, 128.);
3599 relative = victim->coords - oldcoords;
3601 Normalise(&relative);
3602 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3603 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3605 victim->jointVel(abdomen) += relative * damagemult * 200;
3607 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3610 if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3620 award_bonus(id, staffreversebonus);
3622 if (!Tutorial::active) {
3623 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3626 award_bonus(id, staffreversebonus); // Huh, again?
3629 relative = victim->coords - oldcoords;
3631 Normalise(&relative);
3632 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3633 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3635 victim->jointVel(abdomen) += relative * damagemult * 200;
3637 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3640 if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3646 Normalise(&relative);
3648 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3649 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3651 victim->jointVel(lefthand) *= .1;
3652 victim->jointVel(leftwrist) *= .2;
3653 victim->jointVel(leftelbow) *= .5;
3654 victim->jointVel(leftshoulder) *= .7;
3655 victim->jointVel(righthand) *= .1;
3656 victim->jointVel(rightwrist) *= .2;
3657 victim->jointVel(rightelbow) *= .5;
3658 victim->jointVel(rightshoulder) *= .7;
3660 victim->Puff(abdomen);
3661 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3663 award_bonus(id, Reversal);
3667 if (weaponactive != -1 || creature == wolftype) {
3670 if (creature == rabbittype && weaponactive != -1) {
3671 if (weapons[weaponids[0]].getType() == staff) {
3676 if (weaponactive != -1) {
3677 victim->DoBloodBig(2 / victim->armorhigh, 225);
3678 emit_sound_at(knifeslicesound, victim->coords);
3679 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3680 weapons[weaponids[weaponactive]].bloody = 1;
3682 weapons[weaponids[weaponactive]].blooddrip += 3;
3684 if (weaponactive == -1 && creature == wolftype) {
3685 emit_sound_at(clawslicesound, victim->coords, 128.);
3687 victim->DoBloodBig(2 / victim->armorhigh, 175);
3692 if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3698 Normalise(&relative);
3700 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3701 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3703 victim->jointVel(lefthand) *= .1 - 1;
3704 victim->jointVel(leftwrist) *= .2 - 1;
3705 victim->jointVel(leftelbow) *= .5 - 1;
3706 victim->jointVel(leftshoulder) *= .7 - 1;
3707 victim->jointVel(righthand) *= .1 - 1;
3708 victim->jointVel(rightwrist) *= .2 - 1;
3709 victim->jointVel(rightelbow) *= .5 - 1;
3710 victim->jointVel(rightshoulder) *= .7 - 1;
3712 award_bonus(id, swordreversebonus);
3715 if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3724 if (!Tutorial::active) {
3725 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3729 relative = victim->coords - oldcoords;
3731 Normalise(&relative);
3732 relative = DoRotation(relative, 0, -90, 0);
3733 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3734 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3736 victim->jointVel(abdomen) += relative * damagemult * 200;
3737 victim->Puff(abdomen);
3738 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3740 award_bonus(id, Reversal);
3743 if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3746 victim->skeleton.spinny = 0;
3748 relative = facing * -1;
3750 Normalise(&relative);
3751 if (victim->id == 0) {
3754 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3755 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3757 victim->damage = victim->damagetolerance;
3758 victim->permanentdamage = victim->damagetolerance - 1;
3761 if (weaponactive != -1 || creature == wolftype) {
3764 if (creature == rabbittype && weaponactive != -1) {
3765 if (weapons[weaponids[0]].getType() == staff) {
3770 if (weaponactive != -1) {
3771 victim->DoBloodBig(200, 225);
3772 emit_sound_at(knifeslicesound, victim->coords);
3774 weapons[weaponids[weaponactive]].bloody = 2;
3776 weapons[weaponids[weaponactive]].blooddrip += 5;
3779 if (creature == wolftype && weaponactive == -1) {
3780 emit_sound_at(clawslicesound, victim->coords, 128.);
3782 victim->DoBloodBig(2, 175);
3785 award_bonus(id, spinecrusher);
3788 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3789 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3791 if (animTarget == knifefollowanim) {
3792 victim->DoBloodBig(200, 210);
3794 if (animTarget == knifesneakattackanim) {
3795 XYZ footvel, footpoint;
3797 footpoint = weapons[weaponids[0]].tippoint;
3799 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3801 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3802 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3803 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3804 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3805 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3806 victim->DoBloodBig(200, 195);
3807 award_bonus(id, tracheotomy);
3809 if (animTarget == knifefollowanim) {
3810 award_bonus(id, Stabbonus);
3811 XYZ footvel, footpoint;
3813 footpoint = weapons[weaponids[0]].tippoint;
3815 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3817 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3818 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3819 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3820 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3821 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3823 victim->bloodloss += 10000;
3824 victim->velocity = 0;
3825 emit_sound_at(fleshstabsound, victim->coords);
3827 weapons[weaponids[weaponactive]].bloody = 2;
3829 weapons[weaponids[weaponactive]].blooddrip += 5;
3833 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3835 victim->velocity = 0;
3836 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3837 victim->skeleton.joints[i].velocity = 0;
3839 if (animTarget == knifefollowanim) {
3841 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3842 victim->skeleton.joints[i].velocity = 0;
3845 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3846 emit_sound_at(fleshstabremovesound, victim->coords);
3848 weapons[weaponids[weaponactive]].bloody = 2;
3850 weapons[weaponids[weaponactive]].blooddrip += 5;
3852 XYZ footvel, footpoint;
3854 footpoint = weapons[weaponids[0]].tippoint;
3856 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3858 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3859 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3860 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3861 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3862 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3866 if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3867 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3868 award_bonus(id, backstab);
3872 XYZ footvel, footpoint;
3874 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3876 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3878 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3879 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3880 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3881 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3882 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3883 victim->DoBloodBig(200, 180);
3884 victim->DoBloodBig(200, 215);
3885 victim->bloodloss += 10000;
3886 victim->velocity = 0;
3887 emit_sound_at(fleshstabsound, victim->coords);
3889 weapons[weaponids[weaponactive]].bloody = 2;
3891 weapons[weaponids[weaponactive]].blooddrip += 5;
3895 if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3897 victim->velocity = 0;
3898 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3899 victim->skeleton.joints[i].velocity = 0;
3901 if (weaponactive != -1) {
3902 emit_sound_at(fleshstabremovesound, victim->coords);
3904 weapons[weaponids[weaponactive]].bloody = 2;
3906 weapons[weaponids[weaponactive]].blooddrip += 5;
3908 XYZ footvel, footpoint;
3910 footpoint = weapons[weaponids[0]].tippoint;
3912 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3914 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3915 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3916 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3917 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3918 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3922 if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3931 if (weaponactive == -1) {
3932 if (!Tutorial::active) {
3933 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3938 if (weaponactive != -1 || creature == wolftype) {
3941 if (creature == rabbittype && weaponactive != -1) {
3942 if (weapons[weaponids[0]].getType() == staff) {
3947 if (weaponactive != -1) {
3948 victim->DoBloodBig(2 / victim->armorhead, 225);
3949 emit_sound_at(knifeslicesound, victim->coords);
3950 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3951 weapons[weaponids[weaponactive]].bloody = 1;
3953 weapons[weaponids[weaponactive]].blooddrip += 3;
3955 if (weaponactive == -1 && creature == wolftype) {
3956 emit_sound_at(clawslicesound, victim->coords, 128.);
3958 victim->DoBloodBig(2 / victim->armorhead, 175);
3962 award_bonus(id, Reversal);
3967 relative = facing * -1;
3969 Normalise(&relative);
3970 relative = DoRotation(relative, 0, 90, 0);
3972 Normalise(&relative);
3973 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3974 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3976 victim->jointVel(head) += relative * damagemult * 200;
3977 if (victim->damage < victim->damagetolerance - 100) {
3978 victim->velocity = relative * 200;
3980 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3981 victim->velocity = 0;
3984 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))) {
3988 relative = facing * -1;
3990 Normalise(&relative);
3991 relative = DoRotation(relative, 0, 90, 0);
3993 Normalise(&relative);
3994 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3995 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3997 victim->jointVel(head) += relative * damagemult * 200;
4000 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim)) {
4001 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
4002 award_bonus(id, reverseko);
4008 if (frameTarget > int(Animation::animations[animCurrent].frames.size()) - 1) {
4011 animTarget = getIdle();
4012 FootLand(leftfoot, 1);
4013 FootLand(rightfoot, 1);
4015 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
4016 animTarget = rollanim;
4018 emit_sound_at(movewhooshsound, coords, 128.);
4020 if (animCurrent == staggerbackhighanim) {
4021 animTarget = getIdle();
4023 if (animCurrent == staggerbackhardanim) {
4024 animTarget = getIdle();
4026 if (animCurrent == removeknifeanim) {
4027 animTarget = getIdle();
4029 if (animCurrent == crouchremoveknifeanim) {
4030 animTarget = getCrouch();
4032 if (animCurrent == backhandspringanim) {
4033 animTarget = getIdle();
4035 if (animCurrent == dodgebackanim) {
4036 animTarget = getIdle();
4038 if (animCurrent == drawleftanim) {
4039 animTarget = getIdle();
4041 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
4042 animTarget = getIdle();
4043 if (animCurrent == crouchdrawrightanim) {
4044 animTarget = getCrouch();
4046 if (weaponactive == -1) {
4048 } else if (weaponactive == 0) {
4050 if (num_weapons == 2) {
4052 buffer = weaponids[0];
4053 weaponids[0] = weaponids[1];
4054 weaponids[1] = buffer;
4058 if (weaponactive == -1) {
4059 emit_sound_at(knifesheathesound, coords, 128.);
4061 if (weaponactive != -1) {
4062 emit_sound_at(knifedrawsound, coords, 128.);
4065 if (animCurrent == rollanim) {
4066 animTarget = getCrouch();
4067 FootLand(leftfoot, 1);
4068 FootLand(rightfoot, 1);
4071 if (animTarget == walljumprightkickanim) {
4074 if (animTarget == walljumpleftkickanim) {
4077 animTarget = jumpdownanim;
4079 if (animCurrent == climbanim) {
4080 animTarget = getCrouch();
4082 coords += facing * .1;
4083 if (!isnormal(coords.x)) {
4094 if (animTarget == rabbitkickreversalanim) {
4095 animTarget = getCrouch();
4098 if (animTarget == jumpreversalanim) {
4099 animTarget = getCrouch();
4102 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
4103 if (attackkeydown && animTarget != walljumpfrontanim) {
4105 float closestdist = -1;
4107 if (Person::players.size() > 1) {
4108 for (unsigned i = 0; i < Person::players.size(); i++) {
4109 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4110 distance = distsq(&Person::players[i]->coords, &coords);
4111 if (closestdist == -1 || distance < closestdist) {
4112 closestdist = distance;
4118 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4119 victim = Person::players[closest];
4120 animTarget = walljumprightkickanim;
4122 XYZ rotatetarget = victim->coords - coords;
4123 Normalise(&rotatetarget);
4124 yaw = -asin(0 - rotatetarget.x);
4126 if (rotatetarget.z < 0) {
4129 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4130 velocity = (victim->coords - coords) * 4;
4135 if (animTarget == walljumpbackanim) {
4136 animTarget = backflipanim;
4138 velocity = facing * -8;
4141 resume_stream(whooshsound);
4144 if (animTarget == walljumprightanim) {
4145 animTarget = rightflipanim;
4149 velocity = DoRotation(facing, 0, 30, 0) * -8;
4152 if (animTarget == walljumpfrontanim) {
4153 animTarget = frontflipanim;
4157 velocity = facing * 8;
4161 resume_stream(whooshsound);
4164 if (animTarget == walljumpleftanim) {
4165 if (attackkeydown) {
4167 float closestdist = -1;
4169 if (Person::players.size() > 1) {
4170 for (unsigned i = 0; i < Person::players.size(); i++) {
4171 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4172 distance = distsq(&Person::players[i]->coords, &coords);
4173 if (closestdist == -1 || distance < closestdist) {
4174 closestdist = distance;
4180 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4181 victim = Person::players[closest];
4182 animTarget = walljumpleftkickanim;
4184 XYZ rotatetarget = victim->coords - coords;
4185 Normalise(&rotatetarget);
4186 yaw = -asin(0 - rotatetarget.x);
4188 if (rotatetarget.z < 0) {
4191 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4192 velocity = (victim->coords - coords) * 4;
4197 if (animTarget != walljumpleftkickanim) {
4198 animTarget = leftflipanim;
4202 velocity = DoRotation(facing, 0, -30, 0) * -8;
4206 resume_stream(whooshsound);
4209 if (animTarget == sneakattackanim) {
4210 animCurrent = getCrouch();
4211 animTarget = getCrouch();
4218 transspeed = 1000000;
4219 targetheadyaw += 180;
4220 coords -= facing * .7;
4222 coords.y = terrain.getHeight(coords.x, coords.z);
4227 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
4228 animTarget = getIdle();
4231 coords.y = terrain.getHeight(coords.x, coords.z);
4236 if (animCurrent == knifefollowanim) {
4237 animTarget = getIdle();
4240 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
4241 float ycoords = oldcoords.y;
4242 animTarget = getStop();
4247 transspeed = 1000000;
4248 targetheadyaw += 180;
4249 if (!isnormal(coords.x)) {
4252 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim) {
4253 oldcoords = coords + facing * .5;
4254 } else if (animCurrent == sweepreversalanim) {
4255 oldcoords = coords + facing * 1.1;
4256 } else if (animCurrent == upunchreversalanim) {
4257 oldcoords = coords + facing * 1.5;
4260 targetheadyaw += 180;
4263 } else if (animCurrent == knifeslashreversalanim) {
4264 oldcoords = coords + facing * .5;
4267 targetheadyaw += 90;
4270 } else if (animCurrent == staffspinhitreversalanim) {
4273 targetheadyaw += 180;
4278 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
4280 oldcoords.y = ycoords;
4282 currentoffset = coords - oldcoords;
4288 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4293 if (Animation::animations[animTarget].attack == reversed) {
4295 if (animTarget == sweepreversedanim) {
4298 animTarget = backhandspringanim;
4300 emit_sound_at(landsound, coords, 128);
4302 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4303 animTarget = rollanim;
4306 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4307 coords.y = oldcoords.y;
4309 if (animCurrent == knifeslashreversedanim) {
4310 animTarget = rollanim;
4315 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4316 coords.y = oldcoords.y;
4320 animTarget = jumpdownanim;
4323 animTarget = getIdle();
4325 if (wasLandhard()) {
4326 animTarget = getIdle();
4328 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4329 animTarget = getIdle();
4331 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4332 coords.y = oldcoords.y;
4333 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4334 targetoffset.y = coords.y;
4336 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4338 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4339 currentoffset.y -= (coords.y - targetoffset.y);
4340 coords.y = targetoffset.y;
4342 normalsupdatedelay = 0;
4344 if (animCurrent == upunchanim) {
4345 animTarget = getStop();
4346 normalsupdatedelay = 0;
4349 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4353 if (num_weapons > 0) {
4354 if (weapons[0].getType() == staff) {
4363 rabbitkickragdoll = 1;
4365 if (animCurrent == rabbitkickreversedanim) {
4371 skeleton.spinny = 0;
4372 SolidHitBonus(!id); // FIXME: tricky id
4376 animTarget = rollanim;
4379 pause_sound(whooshsound);
4384 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4388 skeleton.spinny = 0;
4390 if (animCurrent == jumpreversedanim) {
4396 skeleton.spinny = 0;
4397 SolidHitBonus(!id); // FIXME: tricky id
4401 animTarget = rollanim;
4402 coords += facing * 2;
4404 pause_sound(whooshsound);
4410 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) {
4411 animTarget = getupfromfrontanim;
4413 } else if (Animation::animations[animCurrent].attack == normalattack) {
4414 animTarget = getIdle();
4417 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4418 animTarget = blockhighleftstrikeanim;
4420 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4421 animTarget = getIdle();
4424 if (animCurrent == spinkickanim && victim->skeleton.free) {
4425 if (creature == rabbittype) {
4426 animTarget = fightidleanim;
4432 if (isIdle() && !wasIdle()) {
4433 normalsupdatedelay = 0;
4436 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4437 animTarget = jumpdownanim;
4440 if (!skeleton.free) {
4442 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4443 if (!isRun() || !wasRun()) {
4444 if (targetFrame().speed > currentFrame().speed) {
4445 target += multiplier * targetFrame().speed * speed * 2;
4447 if (targetFrame().speed <= currentFrame().speed) {
4448 target += multiplier * currentFrame().speed * speed * 2;
4451 if (isRun() && wasRun()) {
4453 tempspeed = velspeed;
4454 if (tempspeed < 10 * speedmult) {
4455 tempspeed = 10 * speedmult;
4457 /* FIXME - mixed of target and current here, is that intended? */
4458 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4460 } else if (transspeed) {
4461 target += multiplier * transspeed * speed * 2;
4463 if (!isRun() || !wasRun()) {
4464 if (targetFrame().speed > currentFrame().speed) {
4465 target += multiplier * targetFrame().speed * 2;
4467 if (targetFrame().speed <= currentFrame().speed) {
4468 target += multiplier * currentFrame().speed * 2;
4473 if (animCurrent != animTarget) {
4474 target = (target + oldtarget) / 2;
4478 frameCurrent = frameTarget;
4482 rot = targetrot * target;
4483 yaw += rot - oldrot;
4489 if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
4490 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4492 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4494 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4495 skeleton.joints[i].position = currentFrame().joints[i].position;
4498 skeleton.FindForwards();
4500 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4501 if (skeleton.muscles[i].visible) {
4502 skeleton.FindRotationMuscle(i, animTarget);
4505 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4506 if (skeleton.muscles[i].visible) {
4507 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4508 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4510 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4511 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4513 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4514 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4520 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4521 skeleton.joints[i].position = targetFrame().joints[i].position;
4524 skeleton.FindForwards();
4526 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4527 if (skeleton.muscles[i].visible) {
4528 skeleton.FindRotationMuscle(i, animTarget);
4531 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4532 if (skeleton.muscles[i].visible) {
4533 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4534 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4536 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4537 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4539 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4540 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4542 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) {
4543 skeleton.muscles[i].newrotate3 -= 360;
4545 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) {
4546 skeleton.muscles[i].newrotate3 += 360;
4548 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) {
4549 skeleton.muscles[i].newrotate2 -= 360;
4551 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) {
4552 skeleton.muscles[i].newrotate2 += 360;
4554 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) {
4555 skeleton.muscles[i].newrotate1 -= 360;
4557 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) {
4558 skeleton.muscles[i].newrotate1 += 360;
4564 oldanimCurrent = animCurrent;
4565 oldanimTarget = animTarget;
4566 oldframeTarget = frameTarget;
4567 oldframeCurrent = frameCurrent;
4569 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4570 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target - skeleton.joints[i].position) / multiplier;
4571 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target;
4573 offset = currentoffset * (1 - target) + targetoffset * target;
4574 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4575 if (skeleton.muscles[i].visible) {
4576 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * target;
4577 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * target;
4578 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * target;
4583 if (isLanding() && landhard) {
4587 animTarget = getLandhard();
4600 void Person::DoStuff()
4602 static XYZ terrainnormal;
4603 static XYZ flatfacing;
4604 static XYZ flatvelocity;
4605 static float flatvelspeed;
4606 static int bloodsize;
4607 static int startx, starty, endx, endy;
4608 static GLubyte color;
4609 static XYZ bloodvel;
4611 onfiredelay -= multiplier;
4612 if (onfiredelay < 0 && onfire) {
4613 if (Random() % 2 == 0) {
4619 crouchkeydowntime += multiplier;
4620 if (!crouchkeydown) {
4621 crouchkeydowntime = 0;
4623 jumpkeydowntime += multiplier;
4624 if (!jumpkeydown && skeleton.free) {
4625 jumpkeydowntime = 0;
4628 if (hostile || damage > 0 || bloodloss > 0) {
4632 if (isIdle() || isRun()) {
4636 if (num_weapons == 1 && weaponactive != -1) {
4641 blooddimamount -= multiplier * .3;
4643 speechdelay -= multiplier;
4644 texupdatedelay -= multiplier;
4645 interestdelay -= multiplier;
4646 flamedelay -= multiplier;
4647 parriedrecently -= multiplier;
4649 victim = this->shared_from_this();
4654 speed = 1.1 * speedmult;
4656 speed = 1.0 * speedmult;
4658 if (!skeleton.free) {
4659 rabbitkickragdoll = 0;
4664 if (id != 0 && (creature == rabbittype || difficulty != 2)) {
4667 if (id != 0 && creature == wolftype && difficulty == 2) {
4669 if (aitype != passivetype) {
4671 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) {
4678 if (animTarget == wolfrunninganim && !superruntoggle) {
4679 animTarget = getRun();
4683 if (weaponactive == -1 && num_weapons > 0) {
4684 if (weapons[weaponids[0]].getType() == staff) {
4690 burnt += multiplier;
4695 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4697 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4704 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
4705 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4709 while (flamedelay < 0 && onfire) {
4711 int howmany = fabs(Random() % (skeleton.joints.size()));
4712 if (skeleton.free) {
4713 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4714 flatfacing = skeleton.joints[howmany].position * scale + coords;
4716 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4717 flatvelocity = (coords - oldcoords) / multiplier / 2;
4719 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4722 while (flamedelay < 0 && !onfire && Tutorial::active && id != 0) {
4724 int howmany = fabs(Random() % (skeleton.joints.size()));
4725 if (skeleton.free) {
4726 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4727 flatfacing = skeleton.joints[howmany].position * scale + coords;
4729 flatvelocity = (coords - oldcoords) / multiplier / 2;
4730 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4732 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4736 bleeding -= multiplier * .3;
4737 if (bloodtoggle == 2) {
4738 skeleton.drawmodel.textureptr.bind();
4739 if ((bleeding <= 0) && (detail != 2)) {
4745 if (neckspurtamount > 0) {
4746 neckspurtamount -= multiplier;
4747 neckspurtdelay -= multiplier * 3;
4748 neckspurtparticledelay -= multiplier * 3;
4749 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4752 if (skeleton.free) {
4753 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4754 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4755 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4757 bloodvel.z = 5 * neckspurtamount;
4758 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4759 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4760 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4762 neckspurtparticledelay = .05;
4764 if (neckspurtdelay < 0) {
4769 if (deathbleeding > 0 && dead != 2) {
4770 if (deathbleeding < 5) {
4771 bleeddelay -= deathbleeding * multiplier / 4;
4773 bleeddelay -= 5 * multiplier / 4;
4775 if (bleeddelay < 0 && bloodtoggle) {
4780 if (skeleton.free) {
4781 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4782 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4784 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4785 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4789 bloodloss += deathbleeding * multiplier * 80;
4790 deathbleeding -= multiplier * 1.6;
4791 if (deathbleeding < 0) {
4794 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4795 if (weaponactive != -1) {
4796 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4797 weapons[weaponids[0]].velocity.x += .01;
4800 weaponids[0] = weaponids[num_weapons];
4801 if (weaponstuck == num_weapons) {
4806 for (unsigned i = 0; i < Person::players.size(); i++) {
4807 Person::players[i]->wentforweapon = 0;
4815 if (!dead && creature == wolftype) {
4816 award_bonus(0, Wolfbonus);
4819 if (animTarget == knifefollowedanim && !skeleton.free) {
4820 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4821 skeleton.joints[i].velocity = 0;
4822 skeleton.joints[i].velocity.y = -2;
4825 if (id != 0 && unconscioustime > .1) {
4833 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4834 texupdatedelay = .12;
4836 bloodsize = 5 - realtexdetail;
4840 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4841 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4842 endx = startx + bloodsize;
4843 endy = starty + bloodsize;
4853 if (endx > skeleton.skinsize - 1) {
4854 endx = skeleton.skinsize - 1;
4857 if (endy > skeleton.skinsize - 1) {
4858 endy = skeleton.skinsize - 1;
4861 if (endx < startx) {
4864 if (endy < starty) {
4868 for (int i = startx; i < endx; i++) {
4869 for (int j = starty; j < endy; j++) {
4870 if (Random() % 2 == 0) {
4871 color = Random() % 85 + 170;
4872 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2) {
4873 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4875 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4876 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4881 skeleton.drawmodel.textureptr.bind();
4885 if (skeleton.free) {
4886 bleedx += 4 * direction / realtexdetail;
4888 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4890 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4893 bleedy -= 4 / realtexdetail;
4895 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4897 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4902 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4903 righthandmorphness = targetrighthandmorphness;
4904 righthandmorphstart = righthandmorphend;
4905 } else if (righthandmorphness > targetrighthandmorphness) {
4906 righthandmorphness -= multiplier * 4;
4907 } else if (righthandmorphness < targetrighthandmorphness) {
4908 righthandmorphness += multiplier * 4;
4911 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4912 lefthandmorphness = targetlefthandmorphness;
4913 lefthandmorphstart = lefthandmorphend;
4914 } else if (lefthandmorphness > targetlefthandmorphness) {
4915 lefthandmorphness -= multiplier * 4;
4916 } else if (lefthandmorphness < targetlefthandmorphness) {
4917 lefthandmorphness += multiplier * 4;
4920 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4921 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4922 tailmorphness = targettailmorphness;
4923 tailmorphstart = tailmorphend;
4924 } else if (tailmorphness > targettailmorphness) {
4925 tailmorphness -= multiplier * 10;
4926 } else if (tailmorphness < targettailmorphness) {
4927 tailmorphness += multiplier * 10;
4931 if (creature == wolftype) {
4932 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4933 tailmorphness = targettailmorphness;
4934 tailmorphstart = tailmorphend;
4935 } else if (tailmorphness > targettailmorphness) {
4936 tailmorphness -= multiplier * 2;
4937 } else if (tailmorphness < targettailmorphness) {
4938 tailmorphness += multiplier * 2;
4942 if (headmorphend == 3 || headmorphstart == 3) {
4943 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4944 headmorphness = targetheadmorphness;
4945 headmorphstart = headmorphend;
4946 } else if (headmorphness > targetheadmorphness) {
4947 headmorphness -= multiplier * 7;
4948 } else if (headmorphness < targetheadmorphness) {
4949 headmorphness += multiplier * 7;
4951 } else if (headmorphend == 5 || headmorphstart == 5) {
4952 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4953 headmorphness = targetheadmorphness;
4954 headmorphstart = headmorphend;
4955 } else if (headmorphness > targetheadmorphness) {
4956 headmorphness -= multiplier * 10;
4957 } else if (headmorphness < targetheadmorphness) {
4958 headmorphness += multiplier * 10;
4961 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4962 headmorphness = targetheadmorphness;
4963 headmorphstart = headmorphend;
4964 } else if (headmorphness > targetheadmorphness) {
4965 headmorphness -= multiplier * 4;
4966 } else if (headmorphness < targetheadmorphness) {
4967 headmorphness += multiplier * 4;
4971 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4972 chestmorphness = targetchestmorphness;
4973 chestmorphstart = chestmorphend;
4974 } else if (chestmorphness > targetchestmorphness) {
4975 chestmorphness -= multiplier;
4976 } else if (chestmorphness < targetchestmorphness) {
4977 chestmorphness += multiplier;
4980 if (dead != 2 && howactive <= typesleeping) {
4981 if (chestmorphstart == 0 && chestmorphend == 0) {
4983 targetchestmorphness = 1;
4986 if (chestmorphstart != 0 && chestmorphend != 0) {
4988 targetchestmorphness = 1;
4990 if (environment == snowyenvironment) {
4993 if (skeleton.free) {
4994 footvel = skeleton.specialforward[0] * -1;
4995 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4997 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4998 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
5000 if (animTarget == sleepanim) {
5001 footvel = DoRotation(footvel, 0, 90, 0);
5003 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
5007 if (!dead && howactive < typesleeping) {
5008 blinkdelay -= multiplier * 2;
5009 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
5011 targetheadmorphness = 1;
5013 blinkdelay = (float)(abs(Random() % 40)) / 5;
5015 if (headmorphstart == 3 && headmorphend == 3) {
5017 targetheadmorphness = 1;
5022 twitchdelay -= multiplier * 1.5;
5023 if (animTarget != hurtidleanim) {
5024 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
5026 targetheadmorphness = 1;
5028 twitchdelay = (float)(abs(Random() % 40)) / 5;
5030 if (headmorphstart == 5 && headmorphend == 5) {
5032 targetheadmorphness = 1;
5036 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
5037 twitchdelay3 -= multiplier * 1;
5038 if (Random() % 2 == 0) {
5039 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
5040 righthandmorphness = 0;
5041 targetrighthandmorphness = 1;
5042 righthandmorphend = 1;
5043 if (Random() % 2 == 0) {
5044 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
5047 if (righthandmorphstart == 1 && righthandmorphend == 1) {
5048 righthandmorphness = 0;
5049 targetrighthandmorphness = 1;
5050 righthandmorphend = 0;
5053 if (Random() % 2 == 0) {
5054 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
5055 lefthandmorphness = 0;
5056 targetlefthandmorphness = 1;
5057 lefthandmorphend = 1;
5058 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
5060 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
5061 lefthandmorphness = 0;
5062 targetlefthandmorphness = 1;
5063 lefthandmorphend = 0;
5069 if (creature == rabbittype) {
5070 if (howactive < typesleeping) {
5071 twitchdelay2 -= multiplier * 1.5;
5073 twitchdelay2 -= multiplier * 0.5;
5075 if (howactive <= typesleeping) {
5076 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
5078 targettailmorphness = 1;
5080 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
5082 if (tailmorphstart == 1 && tailmorphend == 1) {
5084 targettailmorphness = 1;
5087 if (tailmorphstart == 2 && tailmorphend == 2) {
5089 targettailmorphness = 1;
5096 if (creature == wolftype) {
5097 twitchdelay2 -= multiplier * 1.5;
5098 if (tailmorphend != 0) {
5099 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
5101 targettailmorphness = 1;
5106 if (tailmorphend != 5) {
5107 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
5109 targettailmorphness = 1;
5114 if (twitchdelay2 <= 0) {
5115 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
5117 targettailmorphness = 1;
5120 if (tailmorphstart == 1 && tailmorphend == 1) {
5122 targettailmorphness = 1;
5125 if (tailmorphstart == 2 && tailmorphend == 2) {
5127 targettailmorphness = 1;
5130 if (tailmorphstart == 3 && tailmorphend == 3) {
5132 targettailmorphness = 1;
5135 if (tailmorphstart == 4 && tailmorphend == 4) {
5137 targettailmorphness = 1;
5144 unconscioustime = 0;
5147 if (dead == 1 || howactive == typesleeping) {
5148 unconscioustime += multiplier;
5149 //If unconscious, close eyes and mouth
5150 if (righthandmorphend != 0) {
5151 righthandmorphness = 0;
5153 righthandmorphend = 0;
5154 targetrighthandmorphness = 1;
5156 if (lefthandmorphend != 0) {
5157 lefthandmorphness = 0;
5159 lefthandmorphend = 0;
5160 targetlefthandmorphness = 1;
5162 if (headmorphend != 3 && headmorphend != 5) {
5166 targetheadmorphness = 1;
5169 if (howactive > typesleeping) {
5172 if (bloodtoggle && !bled) {
5173 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5174 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5175 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5176 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5180 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5186 if (dead == 2 || howactive > typesleeping) {
5187 //If dead, open mouth and hands
5188 if (righthandmorphend != 0) {
5189 righthandmorphness = 0;
5191 righthandmorphend = 0;
5192 targetrighthandmorphness = 1;
5194 if (lefthandmorphend != 0) {
5195 lefthandmorphness = 0;
5197 lefthandmorphend = 0;
5198 targetlefthandmorphness = 1;
5200 if (headmorphend != 2) {
5204 targetheadmorphness = 1;
5207 if (stunned > 0 && !dead && headmorphend != 2) {
5208 if (headmorphend != 4) {
5212 targetheadmorphness = 1;
5215 if (damage > damagetolerance && !dead) {
5218 unconscioustime = 0;
5220 if (creature == wolftype) {
5221 award_bonus(0, Wolfbonus);
5226 if (weaponactive != -1) {
5227 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5228 weapons[weaponids[0]].velocity.x += .01;
5231 weaponids[0] = weaponids[num_weapons];
5232 if (weaponstuck == num_weapons) {
5237 for (unsigned i = 0; i < Person::players.size(); i++) {
5238 Person::players[i]->wentforweapon = 0;
5242 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
5251 damage -= multiplier * 13;
5252 permanentdamage -= multiplier * 4;
5253 if (isIdle() || isCrouch()) {
5254 permanentdamage -= multiplier * 4;
5260 if (permanentdamage < 0) {
5261 permanentdamage = 0;
5263 if (superpermanentdamage < 0) {
5264 superpermanentdamage = 0;
5266 if (permanentdamage < superpermanentdamage) {
5267 permanentdamage = superpermanentdamage;
5269 if (damage < permanentdamage) {
5270 damage = permanentdamage;
5272 if (dead == 1 && damage < damagetolerance) {
5276 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5277 skeleton.joints[i].velocity = 0;
5280 if (permanentdamage > damagetolerance && dead != 2) {
5283 if (weaponactive != -1) {
5284 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5285 weapons[weaponids[0]].velocity.x += .01;
5288 weaponids[0] = weaponids[num_weapons];
5289 if (weaponstuck == num_weapons) {
5294 for (unsigned i = 0; i < Person::players.size(); i++) {
5295 Person::players[i]->wentforweapon = 0;
5301 if (!dead && creature == wolftype) {
5302 award_bonus(0, Wolfbonus);
5305 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance) {
5306 award_bonus(id, touchofdeath);
5308 if (id != 0 && unconscioustime > .1) {
5316 emit_sound_at(breaksound, coords);
5319 if (skeleton.free == 1) {
5321 pause_sound(whooshsound);
5325 //If knocked over, open hands and close mouth
5326 if (righthandmorphend != 0) {
5327 righthandmorphness = 0;
5329 righthandmorphend = 0;
5330 targetrighthandmorphness = 1;
5332 if (lefthandmorphend != 0) {
5333 lefthandmorphness = 0;
5335 lefthandmorphend = 0;
5336 targetlefthandmorphness = 1;
5338 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
5339 if (headmorphend != 0) {
5343 targetheadmorphness = 1;
5347 skeleton.DoGravity(&scale);
5349 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
5350 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1)) {
5351 award_bonus(id, deepimpact);
5353 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5357 if (!skeleton.joints.empty()) {
5358 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5359 average += skeleton.joints[j].position;
5361 average /= skeleton.joints.size();
5362 coords += average * scale;
5363 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5364 skeleton.joints[j].position -= average;
5366 average /= multiplier;
5370 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5371 velocity += skeleton.joints[i].velocity * scale;
5373 velocity /= skeleton.joints.size();
5375 if (!isnormal(velocity.x) && velocity.x) {
5379 if (findLength(&average) < 10 && dead && skeleton.free) {
5380 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5381 if (skeleton.longdead > 2000) {
5382 if (skeleton.longdead > 6000) {
5384 pause_sound(whooshsound);
5390 if (dead == 2 && bloodloss < damagetolerance) {
5392 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5394 if (bloodtoggle && !bled) {
5395 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5396 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5397 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5398 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5399 float size = .2 * 1.2;
5402 Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5407 if (dead == 2 && bloodloss >= damagetolerance) {
5409 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5410 if (bleeding <= 0) {
5413 if (bloodtoggle && !bled) {
5414 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5415 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5416 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5417 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5421 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5429 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5430 bool canrecover = 1;
5431 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5432 startpoint = coords;
5435 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1) {
5438 if (velocity.y < -30) {
5441 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5442 if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) {
5443 colviewer = startpoint;
5444 coltarget = endpoint;
5445 if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1) {
5455 terrainnormal = jointPos(groin) - jointPos(abdomen);
5456 if (joint(groin).locked && joint(abdomen).locked) {
5457 terrainnormal = jointPos(groin) - jointPos(abdomen);
5458 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5460 if (joint(abdomen).locked && joint(neck).locked) {
5461 terrainnormal = jointPos(abdomen) - jointPos(neck);
5462 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5464 if (joint(groin).locked && joint(neck).locked) {
5465 terrainnormal = jointPos(groin) - jointPos(neck);
5466 middle = (jointPos(groin) + jointPos(neck)) / 2;
5468 Normalise(&terrainnormal);
5470 targetyaw = -asin(0 - terrainnormal.x);
5471 targetyaw *= 360 / 6.28;
5472 if (terrainnormal.z < 0) {
5473 targetyaw = 180 - targetyaw;
5478 animTarget = flipanim;
5479 crouchtogglekeydown = 1;
5484 animCurrent = tempanim;
5488 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5489 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5490 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5495 if (findLength(&average) < 10 && !dead && skeleton.free) {
5496 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5497 if (skeleton.longdead > (damage + 500) * 1.5) {
5499 pause_sound(whooshsound);
5506 terrainnormal = jointPos(groin) - jointPos(abdomen);
5507 if (joint(groin).locked && joint(abdomen).locked) {
5508 terrainnormal = jointPos(groin) - jointPos(abdomen);
5509 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5511 if (joint(abdomen).locked && joint(neck).locked) {
5512 terrainnormal = jointPos(abdomen) - jointPos(neck);
5513 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5515 if (joint(groin).locked && joint(neck).locked) {
5516 terrainnormal = jointPos(groin) - jointPos(neck);
5517 middle = (jointPos(groin) + jointPos(neck)) / 2;
5519 Normalise(&terrainnormal);
5521 targetyaw = -asin(0 - terrainnormal.x);
5522 targetyaw *= 360 / 6.28;
5523 if (terrainnormal.z < 0) {
5524 targetyaw = 180 - targetyaw;
5528 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5530 if (skeleton.forward.y < 0) {
5531 animTarget = getupfrombackanim;
5535 if (skeleton.forward.y > -.3) {
5536 animTarget = getupfromfrontanim;
5544 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5545 animTarget = rollanim;
5546 targetyaw = lookyaw;
5550 if (forwardkeydown) {
5559 if (forwardkeydown) {
5567 if (!leftkeydown && !rightkeydown) {
5575 if (abs(targettilt2) > 50) {
5578 animCurrent = tempanim;
5581 tilt2 = targettilt2;
5583 if (middle.y > 0 && animTarget != rollanim) {
5584 targetoffset.y = middle.y + 1;
5587 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5588 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5589 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5596 if (num_weapons > 0) {
5597 if (weapons[0].getType() == staff) {
5601 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5602 if (velocity.y > -30) {
5604 tempvelocity = velocity;
5605 Normalise(&tempvelocity);
5606 targetyaw = -asin(0 - tempvelocity.x);
5607 targetyaw *= 360 / 6.28;
5608 if (velocity.z < 0) {
5609 targetyaw = 180 - targetyaw;
5614 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5615 animTarget = rollanim;
5618 animTarget = backhandspringanim;
5624 emit_sound_at(movewhooshsound, coords, 128.);
5626 animCurrent = animTarget;
5627 frameCurrent = frameTarget - 1;
5639 if (skeleton.freefall == 0) {
5644 if (aitype != passivetype || skeleton.free == 1) {
5645 if (findLengthfast(&velocity) > .1) {
5646 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5647 if (Object::objects[i]->type == firetype) {
5648 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) {
5650 if (!Object::objects[i]->onfire) {
5651 emit_sound_at(firestartsound, Object::objects[i]->position);
5653 Object::objects[i]->onfire = 1;
5656 if (Object::objects[i]->onfire) {
5662 if (Object::objects[i]->type == bushtype) {
5663 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) {
5665 if (!Object::objects[i]->onfire) {
5666 emit_sound_at(firestartsound, Object::objects[i]->position);
5668 Object::objects[i]->onfire = 1;
5672 if (Object::objects[i]->onfire) {
5676 if (Object::objects[i]->messedwith <= 0) {
5680 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5683 addEnvSound(coords, 4 * findLength(&velocity));
5687 if (environment == grassyenvironment) {
5688 howmany = findLength(&velocity) * 4;
5690 if (environment == snowyenvironment) {
5691 howmany = findLength(&velocity) * 2;
5694 if (environment != desertenvironment) {
5695 for (int j = 0; j < howmany; j++) {
5696 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5697 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5698 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5701 pos.x += float(abs(Random() % 100) - 50) / 200;
5702 pos.y += float(abs(Random() % 100) - 50) / 200;
5703 pos.z += float(abs(Random() % 100) - 50) / 200;
5704 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);
5705 Sprite::setLastSpriteSpecial(1);
5709 howmany = findLength(&velocity) * 4;
5711 if (environment == snowyenvironment) {
5712 for (int j = 0; j < howmany; j++) {
5713 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5714 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5715 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5718 pos.x += float(abs(Random() % 100) - 50) / 200;
5719 pos.y += float(abs(Random() % 100) - 50) / 200;
5720 pos.z += float(abs(Random() % 100) - 50) / 200;
5721 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5722 Sprite::setLastSpriteSpecial(2);
5727 Object::objects[i]->rotx += velocity.x * multiplier * 6;
5728 Object::objects[i]->roty += velocity.z * multiplier * 6;
5729 Object::objects[i]->messedwith = .5;
5733 if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) {
5734 if (Object::objects[i]->pitch == 0) {
5737 tempcoord = coords - Object::objects[i]->position;
5738 tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0);
5739 tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0);
5740 tempcoord += Object::objects[i]->position;
5742 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) {
5743 if (Object::objects[i]->messedwith <= 0) {
5747 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5750 addEnvSound(coords, 4 * findLength(&velocity));
5754 if (environment == grassyenvironment) {
5755 howmany = findLength(&velocity) * 4;
5757 if (environment == snowyenvironment) {
5758 howmany = findLength(&velocity) * 2;
5761 if (environment != desertenvironment) {
5762 for (int j = 0; j < howmany; j++) {
5763 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5764 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5765 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5767 pos += velocity * .1;
5769 pos.x += float(abs(Random() % 100) - 50) / 150;
5770 pos.y += float(abs(Random() % 100) - 50) / 150;
5771 pos.z += float(abs(Random() % 100) - 50) / 150;
5772 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);
5773 Sprite::setLastSpriteSpecial(1);
5777 howmany = findLength(&velocity) * 4;
5779 if (environment == snowyenvironment) {
5780 for (int j = 0; j < howmany; j++) {
5781 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5782 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5783 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5785 pos += velocity * .1;
5787 pos.x += float(abs(Random() % 100) - 50) / 150;
5788 pos.y += float(abs(Random() % 100) - 50) / 150;
5789 pos.z += float(abs(Random() % 100) - 50) / 150;
5790 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5791 Sprite::setLastSpriteSpecial(2);
5796 Object::objects[i]->messedwith = .5;
5803 if (!skeleton.free) {
5806 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype) {
5810 if (aitype != passivetype && victim->skeleton.free && !victim->dead) {
5814 if (Tutorial::active && id != 0) {
5817 if (play && aitype != playercontrolled) {
5818 int whichsound = -1;
5819 if (speechdelay <= 0) {
5820 unsigned int i = abs(Random() % 4);
5822 whichsound = PersonType::types[creature].soundsTalk[i];
5827 if (whichsound != -1) {
5828 emit_sound_at(whichsound, coords);
5832 if (animTarget == staggerbackhighanim) {
5835 if (animTarget == staggerbackhardanim) {
5838 staggerdelay -= multiplier;
5839 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
5842 if (velocity.y < -30 && animTarget == jumpdownanim) {
5845 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5846 animTarget = getIdle();
5850 weaponmissdelay -= multiplier;
5851 highreversaldelay -= multiplier;
5852 lowreversaldelay -= multiplier;
5853 lastcollide -= multiplier;
5854 skiddelay -= multiplier;
5855 if (!isnormal(velocity.x) && velocity.x) {
5858 if (!isnormal(targettilt) && targettilt) {
5861 if (!isnormal(targettilt2) && targettilt2) {
5864 if (!isnormal(targetyaw) && targetyaw) {
5868 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5869 //open hands and close mouth
5870 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5871 righthandmorphness = 0;
5872 righthandmorphend = 0;
5873 targetrighthandmorphness = 1;
5876 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5877 lefthandmorphness = 0;
5878 lefthandmorphend = 0;
5879 targetlefthandmorphness = 1;
5882 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5885 targetheadmorphness = 1;
5889 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) {
5890 //open hands and mouth
5891 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5892 righthandmorphness = 0;
5893 righthandmorphend = 0;
5894 targetrighthandmorphness = 1;
5897 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5898 lefthandmorphness = 0;
5899 lefthandmorphend = 0;
5900 targetlefthandmorphness = 1;
5903 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5906 targetheadmorphness = 1;
5910 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5911 //close hands and mouth
5912 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5913 righthandmorphness = 0;
5914 righthandmorphend = 1;
5915 targetrighthandmorphness = 1;
5918 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5919 lefthandmorphness = 0;
5920 lefthandmorphend = 1;
5921 targetlefthandmorphness = 1;
5924 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5927 targetheadmorphness = 1;
5931 if (animTarget == spinkickanim ||
5932 animTarget == staffspinhitreversalanim ||
5933 animTarget == staffspinhitreversedanim ||
5934 animTarget == staffhitreversalanim ||
5935 animTarget == staffhitreversedanim ||
5936 animTarget == hurtidleanim ||
5937 animTarget == winduppunchanim ||
5938 animTarget == swordslashreversalanim ||
5939 animTarget == swordslashreversedanim ||
5940 animTarget == knifeslashreversalanim ||
5941 animTarget == knifeslashreversedanim ||
5942 animTarget == knifethrowanim ||
5943 animTarget == knifefollowanim ||
5944 animTarget == knifefollowedanim ||
5945 animTarget == killanim ||
5946 animTarget == dropkickanim ||
5947 animTarget == upunchanim ||
5948 animTarget == knifeslashstartanim ||
5949 animTarget == swordslashanim ||
5950 animTarget == staffhitanim ||
5951 animTarget == staffspinhitanim ||
5952 animTarget == staffgroundsmashanim ||
5953 animTarget == spinkickreversalanim ||
5954 animTarget == sweepreversalanim ||
5955 animTarget == lowkickanim ||
5956 animTarget == sweepreversedanim ||
5957 animTarget == rabbitkickreversalanim ||
5958 animTarget == rabbitkickreversedanim ||
5959 animTarget == jumpreversalanim ||
5960 animTarget == jumpreversedanim) {
5961 //close hands and yell
5962 if (righthandmorphend != 1 &&
5963 righthandmorphness == targetrighthandmorphness) {
5964 righthandmorphness = 0;
5965 righthandmorphend = 1;
5966 targetrighthandmorphness = 1;
5969 if (lefthandmorphend != 1 &&
5970 lefthandmorphness == targetlefthandmorphness) {
5971 lefthandmorphness = 0;
5972 lefthandmorphend = 1;
5973 targetlefthandmorphness = 1;
5976 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5979 targetheadmorphness = 1;
5986 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5987 (victim->aitype != searchtype) && (aitype != passivetype) &&
5988 (aitype != searchtype) && (victim->id < Person::players.size())) {
5989 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5993 if (!dead && animTarget != hurtidleanim) {
5994 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5995 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5998 targetheadmorphness = 1;
6003 if (weaponactive != -1) {
6004 if (weapons[weaponids[weaponactive]].getType() != staff) {
6005 righthandmorphstart = 1;
6006 righthandmorphend = 1;
6008 if (weapons[weaponids[weaponactive]].getType() == staff) {
6009 righthandmorphstart = 2;
6010 righthandmorphend = 2;
6012 targetrighthandmorphness = 1;
6015 terrainnormal = terrain.getNormal(coords.x, coords.z);
6017 if (Animation::animations[animTarget].attack != reversal) {
6018 if (!isnormal(coords.x)) {
6027 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
6028 facing = flatfacing;
6029 ReflectVector(&facing, terrainnormal);
6033 animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
6035 targettilt2 = -facing.y * 20;
6041 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim) {
6044 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6045 flatvelocity = velocity;
6047 flatvelspeed = findLength(&flatvelocity);
6048 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
6049 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
6050 if (velocity.y < 0) {
6053 if (velocity.y < 0) {
6056 if (targettilt > 25) {
6059 if (targettilt < -25) {
6064 if (targettilt2 > 45) {
6067 if (targettilt2 < -45) {
6070 if (abs(tilt2 - targettilt2) < multiplier * 400) {
6071 tilt2 = targettilt2;
6072 } else if (tilt2 > targettilt2) {
6073 tilt2 -= multiplier * 400;
6074 } else if (tilt2 < targettilt2) {
6075 tilt2 += multiplier * 400;
6077 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
6086 if (!isnormal(targettilt) && targettilt) {
6089 if (!isnormal(targettilt2) && targettilt2) {
6094 if (animTarget == rabbittackleanim) {
6095 velocity += facing * multiplier * speed * 700 * scale;
6096 velspeed = findLength(&velocity);
6097 if (velspeed > speed * 65 * scale) {
6098 velocity /= velspeed;
6099 velspeed = speed * 65 * scale;
6100 velocity *= velspeed;
6102 velocity.y += gravity * multiplier * 20;
6103 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6104 velspeed = findLength(&velocity);
6105 velocity = flatfacing * velspeed;
6107 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
6108 if (isRun() || animTarget == rabbitkickanim) {
6109 velocity += facing * multiplier * speed * 700 * scale;
6110 velspeed = findLength(&velocity);
6111 if (velspeed > speed * 45 * scale) {
6112 velocity /= velspeed;
6113 velspeed = speed * 45 * scale;
6114 velocity *= velspeed;
6116 velocity.y += gravity * multiplier * 20;
6117 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6118 velspeed = findLength(&velocity);
6119 if (velspeed < speed * 30 * scale) {
6120 velspeed = speed * 30 * scale;
6122 velocity = flatfacing * velspeed;
6124 } else if (isRun()) {
6125 velocity += facing * multiplier * speed * 700 * scale;
6126 velspeed = findLength(&velocity);
6127 if (creature == rabbittype) {
6128 if (velspeed > speed * 55 * scale) {
6129 velocity /= velspeed;
6130 velspeed = speed * 55 * scale;
6131 velocity *= velspeed;
6134 if (creature == wolftype) {
6135 if (velspeed > speed * 75 * scale) {
6136 velocity /= velspeed;
6137 velspeed = speed * 75 * scale;
6138 velocity *= velspeed;
6141 velocity.y += gravity * multiplier * 20;
6142 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6143 velspeed = findLength(&velocity);
6144 velocity = flatfacing * velspeed;
6147 if (animTarget == rollanim && targetFrame().label != 6) {
6148 velocity += facing * multiplier * speed * 700 * scale;
6149 velspeed = findLength(&velocity);
6150 if (velspeed > speed * 45 * scale) {
6151 velocity /= velspeed;
6152 velspeed = speed * 45 * scale;
6153 velocity *= velspeed;
6155 velocity.y += gravity * multiplier * 20;
6156 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6157 velspeed = findLength(&velocity);
6158 velocity = flatfacing * velspeed;
6161 if (animTarget == sneakanim || animTarget == walkanim) {
6162 velocity += facing * multiplier * speed * 700 * scale;
6163 velspeed = findLength(&velocity);
6164 if (velspeed > speed * 12 * scale) {
6165 velocity /= velspeed;
6166 velspeed = speed * 12 * scale;
6167 velocity *= velspeed;
6169 velocity.y += gravity * multiplier * 20;
6170 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6171 velspeed = findLength(&velocity);
6172 velocity = flatfacing * velspeed;
6175 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
6176 velocity += facing * multiplier * speed * 700 * scale;
6177 velspeed = findLength(&velocity);
6178 if (velspeed > speed * 2 * scale) {
6179 velocity /= velspeed;
6180 velspeed = speed * 2 * scale;
6181 velocity *= velspeed;
6183 velocity.y += gravity * multiplier * 20;
6184 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6185 velspeed = findLength(&velocity);
6186 velocity = flatfacing * velspeed;
6189 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
6190 velocity -= facing * multiplier * speed * 700 * scale;
6191 velspeed = findLength(&velocity);
6192 if (velspeed > speed * 2 * scale) {
6193 velocity /= velspeed;
6194 velspeed = speed * 2 * scale;
6195 velocity *= velspeed;
6197 velocity.y += gravity * multiplier * 20;
6198 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6199 velspeed = findLength(&velocity);
6200 velocity = flatfacing * velspeed * -1;
6203 if (animTarget == fightsidestep) {
6204 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
6205 velspeed = findLength(&velocity);
6206 if (velspeed > speed * 12 * scale) {
6207 velocity /= velspeed;
6208 velspeed = speed * 12 * scale;
6209 velocity *= velspeed;
6211 velocity.y += gravity * multiplier * 20;
6212 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6213 velspeed = findLength(&velocity);
6214 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
6217 if (animTarget == staggerbackhighanim) {
6218 coords -= facing * multiplier * speed * 16 * scale;
6221 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
6222 coords -= facing * multiplier * speed * 20 * scale;
6226 if (animTarget == backhandspringanim) {
6227 //coords-=facing*multiplier*50*scale;
6228 velocity += facing * multiplier * speed * 700 * scale * -1;
6229 velspeed = findLength(&velocity);
6230 if (velspeed > speed * 50 * scale) {
6231 velocity /= velspeed;
6232 velspeed = speed * 50 * scale;
6233 velocity *= velspeed;
6235 velocity.y += gravity * multiplier * 20;
6236 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6237 velspeed = findLength(&velocity);
6238 velocity = flatfacing * velspeed * -1;
6240 if (animTarget == dodgebackanim) {
6241 //coords-=facing*multiplier*50*scale;
6242 velocity += facing * multiplier * speed * 700 * scale * -1;
6243 velspeed = findLength(&velocity);
6244 if (velspeed > speed * 60 * scale) {
6245 velocity /= velspeed;
6246 velspeed = speed * 60 * scale;
6247 velocity *= velspeed;
6249 velocity.y += gravity * multiplier * 20;
6250 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6251 velspeed = findLength(&velocity);
6252 velocity = flatfacing * velspeed * -1;
6255 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6256 velspeed = findLength(&velocity);
6259 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6260 velocity.y += gravity * multiplier;
6263 if (animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6264 coords += velocity * multiplier;
6267 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6268 if (isFlip() && targetFrame().label == 7) {
6272 if (animTarget == jumpupanim) {
6274 animTarget = getIdle();
6281 pause_sound(whooshsound);
6282 OPENAL_SetVolume(channels[whooshsound], 0);
6285 if (animTarget == jumpdownanim || isFlip()) {
6289 animTarget = getLanding();
6290 emit_sound_at(landsound, coords, 128.);
6293 addEnvSound(coords);
6298 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6299 coords.y += gravity * multiplier * 2;
6301 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
6302 coords.y = terrain.getHeight(coords.x, coords.z);
6306 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)) {
6307 velspeed = findLength(&velocity);
6309 if (velspeed < multiplier * 300 * scale) {
6312 velocity -= velocity / velspeed * multiplier * 300 * scale;
6314 if (velspeed > 5 && (isLanding() || isLandhard())) {
6315 skiddingdelay += multiplier;
6316 if (skiddelay <= 0) {
6317 FootLand(leftfoot, .5);
6318 FootLand(rightfoot, .5);
6327 velspeed = findLength(&velocity);
6329 if (velspeed > 5 && (isLanding() || isLandhard())) {
6330 skiddingdelay += multiplier;
6331 if (skiddelay <= 0) {
6332 FootLand(leftfoot, .5);
6333 FootLand(rightfoot, .5);
6341 if (skiddingdelay < 0) {
6342 skiddingdelay += multiplier;
6344 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
6346 if (!onterrain || environment == grassyenvironment) {
6347 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
6349 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
6353 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
6354 terrainnormal = victim->coords - coords;
6355 Normalise(&terrainnormal);
6356 targetyaw = -asin(0 - terrainnormal.x);
6357 targetyaw *= 360 / 6.28;
6358 if (terrainnormal.z < 0) {
6359 targetyaw = 180 - targetyaw;
6361 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
6364 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
6365 targetyaw = victim->targetyaw;
6367 if (animTarget == rabbittacklinganim) {
6368 coords = victim->coords;
6371 skeleton.oldfree = skeleton.free;
6375 midterrain.x = terrain.size * terrain.scale / 2;
6376 midterrain.z = terrain.size * terrain.scale / 2;
6377 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
6379 tempposit = coords - midterrain;
6381 Normalise(&tempposit);
6382 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
6383 coords.x = tempposit.x + midterrain.x;
6384 coords.z = tempposit.z + midterrain.z;
6389 * inverse kinematics helper function
6391 void IKHelper(Person* p, float interp)
6393 XYZ point, change, change2;
6394 float heightleft, heightright;
6396 // TODO: implement localToWorld and worldToLocal
6397 // but keep in mind it won't be the same math if player is ragdolled or something
6398 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
6399 // then comb through code for places where to use it
6401 // point = localToWorld(jointPos(leftfoot))
6402 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
6403 // adjust height of foot
6404 heightleft = terrain.getHeight(point.x, point.z) + .04;
6405 point.y = heightleft;
6406 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
6407 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
6408 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
6409 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
6410 // move ankle along with foot
6411 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
6412 // average knee pos between old and new pos
6413 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
6415 // do same as above for right leg
6416 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
6417 heightright = terrain.getHeight(point.x, point.z) + .04;
6418 point.y = heightright;
6419 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
6420 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
6421 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
6422 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
6423 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
6425 // fix up skeleton now that we've moved body parts?
6426 p->skeleton.DoConstraints(&p->coords, &p->scale);
6433 int Person::DrawSkeleton()
6435 int oldplayerdetail;
6436 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6437 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6447 glAlphaFunc(GL_GREATER, 0.0001);
6449 float terrainheight;
6451 if (!isnormal(yaw)) {
6454 if (!isnormal(tilt)) {
6457 if (!isnormal(tilt2)) {
6460 oldplayerdetail = playerdetail;
6462 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6465 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6468 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6474 if (playerdetail != oldplayerdetail) {
6476 normalsupdatedelay = 0;
6478 static float updatedelaychange;
6479 static float morphness;
6480 static float framemult;
6482 skeleton.FindForwards();
6483 if (howactive == typesittingwall) {
6484 skeleton.specialforward[1] = 0;
6485 skeleton.specialforward[1].z = 1;
6491 static int weaponattachmuscle;
6492 static int weaponrotatemuscle;
6493 static XYZ weaponpoint;
6494 static int start, endthing;
6495 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6496 if (!isSleeping() && !isSitting()) {
6497 // TODO: give these meaningful names
6498 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6499 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard() || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6501 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6503 if (creature == wolftype) {
6508 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6509 IKHelper(this, target);
6510 if (creature == wolftype) {
6511 IKHelper(this, target);
6515 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6516 IKHelper(this, 1 - target);
6517 if (creature == wolftype) {
6518 IKHelper(this, 1 - target);
6523 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())) {
6526 targetheadyaw = -targetyaw;
6527 targetheadpitch = 0;
6528 if (Animation::animations[animTarget].attack == 3) {
6529 targetheadyaw += 180;
6532 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6533 skeleton.drawmodel.vertex[i] = 0;
6534 skeleton.drawmodel.vertex[i].y = 999;
6536 for (int i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6537 skeleton.drawmodellow.vertex[i] = 0;
6538 skeleton.drawmodellow.vertex[i].y = 999;
6540 for (int i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6541 skeleton.drawmodelclothes.vertex[i] = 0;
6542 skeleton.drawmodelclothes.vertex[i].y = 999;
6544 for (unsigned int i = 0; i < skeleton.muscles.size(); i++) {
6545 // convenience renames
6546 const int p1 = skeleton.muscles[i].parent1->label;
6547 const int p2 = skeleton.muscles[i].parent2->label;
6549 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6554 if (p1 == righthand || p2 == righthand) {
6555 morphness = righthandmorphness;
6556 start = righthandmorphstart;
6557 endthing = righthandmorphend;
6559 if (p1 == lefthand || p2 == lefthand) {
6560 morphness = lefthandmorphness;
6561 start = lefthandmorphstart;
6562 endthing = lefthandmorphend;
6564 if (p1 == head || p2 == head) {
6565 morphness = headmorphness;
6566 start = headmorphstart;
6567 endthing = headmorphend;
6569 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6570 morphness = chestmorphness;
6571 start = chestmorphstart;
6572 endthing = chestmorphend;
6574 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6575 morphness = tailmorphness;
6576 start = tailmorphstart;
6577 endthing = tailmorphend;
6580 skeleton.FindRotationMuscle(i, animTarget);
6582 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6583 glMatrixMode(GL_MODELVIEW);
6586 if (!skeleton.free) {
6587 glRotatef(tilt2, 1, 0, 0);
6589 if (!skeleton.free) {
6590 glRotatef(tilt, 0, 0, 1);
6593 glTranslatef(mid.x, mid.y, mid.z);
6595 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6596 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6598 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6599 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6601 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6602 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6604 if (playerdetail || skeleton.free == 3) {
6605 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6606 XYZ& v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6607 XYZ& v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6608 glMatrixMode(GL_MODELVIEW);
6610 if (p1 == abdomen || p2 == abdomen) {
6611 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(1).x,
6612 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(1).y,
6613 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(1).z);
6615 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6616 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(2).x,
6617 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(2).y,
6618 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(2).z);
6620 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6621 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(3).x,
6622 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(3).y,
6623 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(3).z);
6625 if (p1 == head || p2 == head) {
6626 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(0).x,
6627 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(0).y,
6628 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(0).z);
6630 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6631 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6632 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6633 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6637 if (!playerdetail || skeleton.free == 3) {
6638 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6639 XYZ& v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6640 glMatrixMode(GL_MODELVIEW);
6642 if (p1 == abdomen || p2 == abdomen) {
6643 glTranslatef(v0.x * getProportion(1).x,
6644 v0.y * getProportion(1).y,
6645 v0.z * getProportion(1).z);
6647 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6648 glTranslatef(v0.x * getProportion(2).x,
6649 v0.y * getProportion(2).y,
6650 v0.z * getProportion(2).z);
6652 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6653 glTranslatef(v0.x * getProportion(3).x,
6654 v0.y * getProportion(3).y,
6655 v0.z * getProportion(3).z);
6657 if (p1 == head || p2 == head) {
6658 glTranslatef(v0.x * getProportion(0).x,
6659 v0.y * getProportion(0).y,
6660 v0.z * getProportion(0).z);
6663 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6664 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6665 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6666 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6672 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6673 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6675 glMatrixMode(GL_MODELVIEW);
6678 if (!skeleton.free) {
6679 glRotatef(tilt2, 1, 0, 0);
6681 if (!skeleton.free) {
6682 glRotatef(tilt, 0, 0, 1);
6684 glTranslatef(mid.x, mid.y, mid.z);
6685 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6686 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6688 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6689 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6691 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6692 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6694 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6695 XYZ& v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6696 glMatrixMode(GL_MODELVIEW);
6698 if (p1 == abdomen || p2 == abdomen) {
6699 glTranslatef(v0.x * getProportion(1).x,
6700 v0.y * getProportion(1).y,
6701 v0.z * getProportion(1).z);
6703 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6704 glTranslatef(v0.x * getProportion(2).x,
6705 v0.y * getProportion(2).y,
6706 v0.z * getProportion(2).z);
6708 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6709 glTranslatef(v0.x * getProportion(3).x,
6710 v0.y * getProportion(3).y,
6711 v0.z * getProportion(3).z);
6713 if (p1 == head || p2 == head) {
6714 glTranslatef(v0.x * getProportion(0).x,
6715 v0.y * getProportion(0).y,
6716 v0.z * getProportion(0).z);
6718 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6719 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6720 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6721 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6726 updatedelay = 1 + (float)(Random() % 100) / 1000;
6728 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6729 normalsupdatedelay = 1;
6730 if (playerdetail || skeleton.free == 3) {
6731 skeleton.drawmodel.CalculateNormals(0);
6733 if (!playerdetail || skeleton.free == 3) {
6734 skeleton.drawmodellow.CalculateNormals(0);
6736 if (skeleton.clothes) {
6737 skeleton.drawmodelclothes.CalculateNormals(0);
6740 if (playerdetail || skeleton.free == 3) {
6741 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6743 if (!playerdetail || skeleton.free == 3) {
6744 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6746 if (skeleton.clothes) {
6747 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6752 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6753 if (updatedelaychange > -realmultiplier * 30) {
6754 updatedelaychange = -realmultiplier * 30;
6756 if (updatedelaychange > -framemult * 4) {
6757 updatedelaychange = -framemult * 4;
6759 if (skeleton.free == 1) {
6760 updatedelaychange *= 6;
6763 updatedelaychange *= 8;
6765 updatedelay += updatedelaychange;
6767 glMatrixMode(GL_MODELVIEW);
6769 glTranslatef(coords.x, coords.y - .02, coords.z);
6770 if (!skeleton.free) {
6771 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6772 glRotatef(yaw, 0, 1, 0);
6776 glColor4f(.4, 1, .4, 1);
6777 glDisable(GL_LIGHTING);
6778 glDisable(GL_TEXTURE_2D);
6781 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6782 XYZ& v0 = skeleton.drawmodel.vertex[i];
6783 glVertex3f(v0.x, v0.y, v0.z);
6790 for (unsigned int i = 0; i < skeleton.drawmodel.Triangles.size(); i++) {
6791 const XYZ& v0 = skeleton.drawmodel.getTriangleVertex(i, 0);
6792 const XYZ& v1 = skeleton.drawmodel.getTriangleVertex(i, 1);
6793 const XYZ& v2 = skeleton.drawmodel.getTriangleVertex(i, 2);
6794 glVertex3f(v0.x, v0.y, v0.z);
6795 glVertex3f(v1.x, v1.y, v1.z);
6796 glVertex3f(v1.x, v1.y, v1.z);
6797 glVertex3f(v2.x, v2.y, v2.z);
6798 glVertex3f(v2.x, v2.y, v2.z);
6799 glVertex3f(v0.x, v0.y, v0.z);
6806 terrainlight = terrain.getLighting(coords.x, coords.z);
6807 distance = distsq(&viewer, &coords);
6808 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6813 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6814 if (terrainheight < 1) {
6817 if (terrainheight > 1.7) {
6818 terrainheight = 1.7;
6821 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6822 glDisable(GL_BLEND);
6823 glAlphaFunc(GL_GREATER, 0.0001);
6824 glEnable(GL_TEXTURE_2D);
6826 glDisable(GL_TEXTURE_2D);
6827 glColor4f(.7, .35, 0, .5);
6829 glEnable(GL_LIGHTING);
6832 if (Tutorial::active && id != 0) {
6833 glColor4f(.7, .7, .7, 0.6);
6835 glEnable(GL_LIGHTING);
6837 if (canattack && cananger) {
6838 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6839 glDisable(GL_TEXTURE_2D);
6840 glColor4f(1, 0, 0, 0.8);
6843 glMatrixMode(GL_TEXTURE);
6845 glTranslatef(0, -smoketex, 0);
6846 glTranslatef(-smoketex, 0, 0);
6850 if (Tutorial::active && (id != 0)) {
6851 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6853 skeleton.drawmodel.draw();
6857 if (!playerdetail) {
6858 if (Tutorial::active && (id != 0)) {
6859 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6861 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6865 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed)) {
6866 if (Tutorial::active && id != 0) {
6868 glMatrixMode(GL_MODELVIEW);
6869 glEnable(GL_TEXTURE_2D);
6870 glColor4f(.7, .7, .7, 0.6);
6872 glEnable(GL_LIGHTING);
6874 if (canattack && cananger) {
6875 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6876 glDisable(GL_TEXTURE_2D);
6877 glColor4f(1, 0, 0, 0.8);
6880 glMatrixMode(GL_TEXTURE);
6882 glTranslatef(0, -smoketex * .6, 0);
6883 glTranslatef(smoketex * .6, 0, 0);
6886 if (Tutorial::active && (id != 0)) {
6887 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6889 skeleton.drawmodel.draw();
6893 if (!playerdetail) {
6894 if (Tutorial::active && (id != 0)) {
6895 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6897 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6903 if (Tutorial::active && id != 0) {
6905 glMatrixMode(GL_MODELVIEW);
6906 glEnable(GL_TEXTURE_2D);
6908 if (skeleton.clothes) {
6912 skeleton.drawmodelclothes.draw();
6915 skeleton.drawmodelclothes.drawimmediate();
6922 if (num_weapons > 0) {
6923 for (k = 0; k < num_weapons; k++) {
6924 int i = weaponids[k];
6925 if (weaponactive == k) {
6926 if (weapons[i].getType() != staff) {
6927 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6928 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6929 weaponattachmuscle = j;
6932 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6933 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) {
6934 weaponrotatemuscle = j;
6937 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6938 if (creature == wolftype) {
6939 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6942 if (weapons[i].getType() == staff) {
6943 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6944 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6945 weaponattachmuscle = j;
6948 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6949 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) {
6950 weaponrotatemuscle = j;
6953 //weaponpoint=jointPos(rightwrist);
6954 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6955 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6956 XYZ tempnormthing, vec1, vec2;
6957 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6958 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6959 CrossProduct(&vec1, &vec2, &tempnormthing);
6960 Normalise(&tempnormthing);
6961 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim) {
6962 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6966 if (weaponactive != k && weaponstuck != k) {
6967 if (weapons[i].getType() == knife) {
6968 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6970 if (weapons[i].getType() == sword) {
6971 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6973 if (weapons[i].getType() == staff) {
6974 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6976 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6977 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) {
6978 weaponrotatemuscle = j;
6982 if (weaponstuck == k) {
6983 if (weaponstuckwhere == 0) {
6984 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6986 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6988 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6989 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) {
6990 weaponrotatemuscle = j;
6994 if (skeleton.free) {
6995 weapons[i].position = weaponpoint * scale + coords;
6996 weapons[i].bigrotation = 0;
6997 weapons[i].bigtilt = 0;
6998 weapons[i].bigtilt2 = 0;
7000 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;
7001 weapons[i].bigrotation = yaw;
7002 weapons[i].bigtilt = tilt;
7003 weapons[i].bigtilt2 = tilt2;
7005 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
7006 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
7007 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
7008 if (weaponactive == k) {
7009 if (weapons[i].getType() == knife) {
7010 weapons[i].smallrotation = 180;
7011 weapons[i].smallrotation2 = 0;
7012 if (isCrouch() || wasCrouch()) {
7013 weapons[i].smallrotation2 = 20;
7015 if (animTarget == hurtidleanim) {
7016 weapons[i].smallrotation2 = 50;
7018 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
7019 XYZ temppoint1, temppoint2;
7022 temppoint1 = jointPos(righthand);
7023 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7024 distance = findDistance(&temppoint1, &temppoint2);
7025 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7026 weapons[i].rotation2 *= 360 / 6.28;
7029 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7030 weapons[i].rotation1 *= 360 / 6.28;
7031 weapons[i].rotation3 = 0;
7032 weapons[i].smallrotation = -90;
7033 weapons[i].smallrotation2 = 0;
7034 if (temppoint1.x > temppoint2.x) {
7035 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7038 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
7039 XYZ temppoint1, temppoint2;
7042 temppoint1 = jointPos(righthand);
7043 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7044 distance = findDistance(&temppoint1, &temppoint2);
7045 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7046 weapons[i].rotation2 *= 360 / 6.28;
7049 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7050 weapons[i].rotation1 *= 360 / 6.28;
7051 weapons[i].rotation3 = 0;
7052 weapons[i].smallrotation = 90;
7053 weapons[i].smallrotation2 = 0;
7054 if (temppoint1.x > temppoint2.x) {
7055 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7058 if (animTarget == knifethrowanim) {
7059 weapons[i].smallrotation = 90;
7060 //weapons[i].smallrotation2=-90;
7061 weapons[i].smallrotation2 = 0;
7062 weapons[i].rotation1 = 0;
7063 weapons[i].rotation2 = 0;
7064 weapons[i].rotation3 = 0;
7066 if (animTarget == knifesneakattackanim && frameTarget < 5) {
7067 weapons[i].smallrotation = -90;
7068 weapons[i].rotation1 = 0;
7069 weapons[i].rotation2 = 0;
7070 weapons[i].rotation3 = 0;
7073 if (weapons[i].getType() == sword) {
7074 weapons[i].smallrotation = 0;
7075 weapons[i].smallrotation2 = 0;
7076 if (animTarget == knifethrowanim) {
7077 weapons[i].smallrotation = -90;
7078 weapons[i].smallrotation2 = 0;
7079 weapons[i].rotation1 = 0;
7080 weapons[i].rotation2 = 0;
7081 weapons[i].rotation3 = 0;
7083 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)) {
7084 XYZ temppoint1, temppoint2;
7087 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
7088 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7089 distance = findDistance(&temppoint1, &temppoint2);
7090 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7091 weapons[i].rotation2 *= 360 / 6.28;
7094 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7095 weapons[i].rotation1 *= 360 / 6.28;
7096 weapons[i].rotation3 = 0;
7097 weapons[i].smallrotation = 90;
7098 weapons[i].smallrotation2 = 0;
7099 if (temppoint1.x > temppoint2.x) {
7100 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7104 if (weapons[i].getType() == staff) {
7105 weapons[i].smallrotation = 100;
7106 weapons[i].smallrotation2 = 0;
7107 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
7108 XYZ temppoint1, temppoint2;
7111 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
7112 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7113 distance = findDistance(&temppoint1, &temppoint2);
7114 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7115 weapons[i].rotation2 *= 360 / 6.28;
7118 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7119 weapons[i].rotation1 *= 360 / 6.28;
7120 weapons[i].rotation3 = 0;
7121 weapons[i].smallrotation = 90;
7122 weapons[i].smallrotation2 = 0;
7123 if (temppoint1.x > temppoint2.x) {
7124 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7129 if (weaponactive != k && weaponstuck != k) {
7130 if (weapons[i].getType() == knife) {
7131 weapons[i].smallrotation = -70;
7132 weapons[i].smallrotation2 = 10;
7134 if (weapons[i].getType() == sword) {
7135 weapons[i].smallrotation = -100;
7136 weapons[i].smallrotation2 = -8;
7138 if (weapons[i].getType() == staff) {
7139 weapons[i].smallrotation = -100;
7140 weapons[i].smallrotation2 = -8;
7143 if (weaponstuck == k) {
7144 if (weaponstuckwhere == 0) {
7145 weapons[i].smallrotation = 180;
7147 weapons[i].smallrotation = 0;
7149 weapons[i].smallrotation2 = 10;
7156 if (skeleton.free) {
7159 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump()) {
7162 if (animCurrent != animTarget) {
7165 if (skeleton.free == 2) {
7174 int Person::SphereCheck(XYZ* p1, float radius, XYZ* p, XYZ* move, float* rotate, Model* model)
7176 static float distance;
7177 static float olddistance;
7178 static int intersecting;
7179 static int firstintersecting;
7182 static XYZ start, end;
7183 static float slopethreshold = -.4;
7185 firstintersecting = -1;
7189 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius) {
7193 *p1 = DoRotation(*p1, 0, -*rotate, 0);
7195 for (int i = 0; i < 4; i++) {
7196 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7197 if (model->Triangles[j].facenormal.y <= slopethreshold) {
7199 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)));
7200 if (distance < radius) {
7201 point = *p1 - model->Triangles[j].facenormal * distance;
7202 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]])) {
7205 if (!intersecting) {
7206 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7207 &model->vertex[model->Triangles[j].vertex[1]],
7210 if (!intersecting) {
7211 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
7212 &model->vertex[model->Triangles[j].vertex[2]],
7215 if (!intersecting) {
7216 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7217 &model->vertex[model->Triangles[j].vertex[2]],
7221 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7225 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)) {
7226 p1->y = point.y + radius;
7227 if ((animTarget == jumpdownanim || isFlip())) {
7228 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4)) {
7232 if (animTarget == jumpupanim) {
7234 animTarget = getIdle();
7241 pause_sound(whooshsound);
7242 OPENAL_SetVolume(channels[whooshsound], 0);
7245 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
7249 animTarget = getLanding();
7250 emit_sound_at(landsound, coords, 128.);
7253 addEnvSound(coords);
7260 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7261 olddistance = distance;
7262 firstintersecting = j;
7267 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7268 if (model->Triangles[j].facenormal.y > slopethreshold) {
7271 start.y -= radius / 4;
7272 XYZ& v0 = model->vertex[model->Triangles[j].vertex[0]];
7273 XYZ& v1 = model->vertex[model->Triangles[j].vertex[1]];
7274 XYZ& v2 = model->vertex[model->Triangles[j].vertex[2]];
7275 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)));
7276 if (distance < radius * .5) {
7277 point = start - model->Triangles[j].facenormal * distance;
7278 if (PointInTriangle(&point, model->Triangles[j].facenormal, &v0, &v1, &v2)) {
7281 if (!intersecting) {
7282 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
7284 if (!intersecting) {
7285 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7287 if (!intersecting) {
7288 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7291 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7292 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
7294 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;
7295 if (findLengthfast(&start) < findLengthfast(&velocity)) {
7299 *p1 += model->Triangles[j].facenormal * (distance - radius * .5);
7302 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7303 olddistance = distance;
7304 firstintersecting = j;
7311 *p = DoRotation(*p, 0, *rotate, 0);
7315 *p1 = DoRotation(*p1, 0, *rotate, 0);
7318 return firstintersecting;
7321 int findPathDist(int start, int end)
7326 unsigned int smallestcount = 1000;
7327 for (char i = 0; i < 50; i++) {
7328 unsigned int count = 0;
7333 while (last != end && count < 30) {
7335 for (int j = 0; j < Game::numpathpoints; j++) {
7336 if (j != last && j != last2 && j != last3 && j != last4) {
7338 if (Game::numpathpointconnect[j]) {
7339 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7340 if (Game::pathpointconnect[j][k] == last) {
7346 if (Game::numpathpointconnect[last]) {
7347 for (int k = 0; k < Game::numpathpointconnect[last]; k++) {
7348 if (Game::pathpointconnect[last][k] == j) {
7355 if (closest == -1 || Random() % 2 == 0) {
7367 if (count < smallestcount) {
7368 smallestcount = count;
7371 return smallestcount;
7374 void Person::takeWeapon(int weaponId)
7377 weapons[weaponId].owner = id;
7378 if (num_weapons > 0) {
7379 weaponids[num_weapons] = weaponids[0];
7382 weaponids[0] = weaponId;
7385 void Person::addClothes()
7387 if (numclothes > 0) {
7388 for (int i = 0; i < numclothes; i++) {
7395 bool Person::addClothes(const int& clothesId)
7398 const std::string fileName = clothes[clothesId];
7400 GLubyte* array = &skeleton.skinText[0];
7404 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
7409 float tintr = clothestintr[clothesId];
7410 float tintg = clothestintg[clothesId];
7411 float tintb = clothestintb[clothesId];
7433 int bytesPerPixel = texture.bpp / 8;
7437 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
7438 if (bytesPerPixel == 3) {
7440 } else if ((i + 1) % 4 == 0) {
7441 alphanum = texture.data[i];
7443 if ((i + 1) % 4 || bytesPerPixel == 3) {
7445 texture.data[i] *= tintr;
7448 texture.data[i] *= tintg;
7451 texture.data[i] *= tintb;
7453 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
7465 if (aitype != playercontrolled && !Dialog::inDialog()) {
7467 //disable movement in editor
7468 if (Game::editorenabled) {
7473 if (distsqflat(&Person::players[0]->coords, &coords) < 30 &&
7474 Person::players[0]->coords.y > coords.y + 2 &&
7475 !Person::players[0]->onterrain) {
7480 if (aitype == pathfindtype) {
7481 if (finalpathfindpoint == -1) {
7482 float closestdistance;
7483 float tempdist = 0.0f;
7487 closestdistance = -1;
7488 for (int j = 0; j < Game::numpathpoints; j++) {
7489 if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) {
7490 closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]);
7492 finaltarget = Game::pathpoint[j];
7495 finalpathfindpoint = closest;
7496 for (int j = 0; j < Game::numpathpoints; j++) {
7497 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7498 DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7499 if (sq(tempdist) < closestdistance) {
7500 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7501 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7502 closestdistance = sq(tempdist);
7504 finaltarget = colpoint;
7509 finalpathfindpoint = closest;
7511 if (targetpathfindpoint == -1) {
7512 float closestdistance;
7513 float tempdist = 0.0f;
7517 closestdistance = -1;
7518 if (lastpathfindpoint == -1) {
7519 for (int j = 0; j < Game::numpathpoints; j++) {
7520 if (j != lastpathfindpoint) {
7521 if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) {
7522 closestdistance = distsq(&coords, &Game::pathpoint[j]);
7527 targetpathfindpoint = closest;
7528 for (int j = 0; j < Game::numpathpoints; j++) {
7529 if (j != lastpathfindpoint) {
7530 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7531 DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7532 if (sq(tempdist) < closestdistance) {
7533 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7534 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7535 closestdistance = sq(tempdist);
7542 targetpathfindpoint = closest;
7544 for (int j = 0; j < Game::numpathpoints; j++) {
7545 if (j != lastpathfindpoint &&
7546 j != lastpathfindpoint2 &&
7547 j != lastpathfindpoint3 &&
7548 j != lastpathfindpoint4) {
7550 if (Game::numpathpointconnect[j]) {
7551 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7552 if (Game::pathpointconnect[j][k] == lastpathfindpoint) {
7558 if (Game::numpathpointconnect[lastpathfindpoint]) {
7559 for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++) {
7560 if (Game::pathpointconnect[lastpathfindpoint][k] == j) {
7567 tempdist = findPathDist(j, finalpathfindpoint);
7568 if (closest == -1 || tempdist < closestdistance) {
7569 closestdistance = tempdist;
7575 targetpathfindpoint = closest;
7578 losupdatedelay -= multiplier;
7580 targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]);
7581 lookyaw = targetyaw;
7583 //reached target point
7584 if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) {
7585 lastpathfindpoint4 = lastpathfindpoint3;
7586 lastpathfindpoint3 = lastpathfindpoint2;
7587 lastpathfindpoint2 = lastpathfindpoint;
7588 lastpathfindpoint = targetpathfindpoint;
7589 if (lastpathfindpoint2 == -1) {
7590 lastpathfindpoint2 = lastpathfindpoint;
7592 if (lastpathfindpoint3 == -1) {
7593 lastpathfindpoint3 = lastpathfindpoint2;
7595 if (lastpathfindpoint4 == -1) {
7596 lastpathfindpoint4 = lastpathfindpoint3;
7598 targetpathfindpoint = -1;
7600 if (distsqflat(&coords, &finalfinaltarget) <
7601 distsqflat(&coords, &finaltarget) ||
7602 distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) ||
7603 lastpathfindpoint == finalpathfindpoint) {
7604 aitype = passivetype;
7615 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7616 targetyaw += 90 * (whichdirection * 2 - 1);
7619 if (collided < 1 || animTarget != jumpupanim) {
7622 if ((collided > .8 && jumppower >= 5)) {
7626 if ((!Tutorial::active || cananger) &&
7628 !Person::players[0]->dead &&
7629 distsq(&coords, &Person::players[0]->coords) < 400 &&
7631 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7632 Animation::animations[Person::players[0]->animTarget].height != lowheight &&
7633 !Game::editorenabled &&
7634 (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain)) {
7635 aitype = attacktypecutoff;
7637 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7638 Animation::animations[Person::players[0]->animTarget].height == highheight &&
7639 !Game::editorenabled) {
7640 aitype = attacktypecutoff;
7643 if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7644 losupdatedelay = .2;
7645 for (unsigned j = 0; j < Person::players.size(); j++) {
7646 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7647 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7648 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7649 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7650 if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain) {
7651 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) ||
7652 (Person::players[j]->animTarget == hanganim &&
7653 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7654 aitype = searchtype;
7656 lastseen = Person::players[j]->coords;
7667 if (aitype == attacktypecutoff && Game::musictype != 2) {
7668 if (creature != wolftype) {
7675 if (aitype != passivetype && Game::leveltime > .5) {
7676 howactive = typeactive;
7679 if (aitype == passivetype) {
7680 aiupdatedelay -= multiplier;
7681 losupdatedelay -= multiplier;
7682 lastseentime += multiplier;
7683 pausetime -= multiplier;
7684 if (lastseentime > 1) {
7688 if (aiupdatedelay < 0) {
7689 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7690 targetyaw = roughDirectionTo(coords, waypoints[waypoint]);
7691 lookyaw = targetyaw;
7692 aiupdatedelay = .05;
7694 if (distsqflat(&coords, &waypoints[waypoint]) < 1) {
7695 if (waypointtype[waypoint] == wppause) {
7699 if (waypoint > numwaypoints - 1) {
7705 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7717 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7718 if (!avoidsomething) {
7719 targetyaw += 90 * (whichdirection * 2 - 1);
7721 XYZ leftpos, rightpos;
7722 float leftdist, rightdist;
7723 leftpos = coords + DoRotation(facing, 0, 90, 0);
7724 rightpos = coords - DoRotation(facing, 0, 90, 0);
7725 leftdist = distsq(&leftpos, &avoidwhere);
7726 rightdist = distsq(&rightpos, &avoidwhere);
7727 if (leftdist < rightdist) {
7735 if (collided < 1 || animTarget != jumpupanim) {
7738 if ((collided > .8 && jumppower >= 5)) {
7743 if (!Game::editorenabled) {
7744 if (howactive <= typesleeping) {
7745 if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile) {
7746 for (int j = 0; j < numenvsounds; j++) {
7747 float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
7748 if (vol > 0 && distsq(&coords, &envsound[j]) < 2 * (vol + vol * (creature == rabbittype) * 3)) {
7749 aitype = attacktypecutoff;
7755 if (aitype != passivetype) {
7756 if (howactive == typesleeping) {
7757 setTargetAnimation(getupfromfrontanim);
7759 howactive = typeactive;
7763 if (howactive < typesleeping &&
7764 ((!Tutorial::active || cananger) && hostile) &&
7765 !Person::players[0]->dead &&
7766 distsq(&coords, &Person::players[0]->coords) < 400 &&
7768 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7769 Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled) {
7770 aitype = attacktypecutoff;
7772 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7773 Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled) {
7774 aitype = attacktypecutoff;
7778 if (creature == wolftype) {
7780 for (unsigned j = 0; j < Person::players.size(); j++) {
7781 if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
7782 float smelldistance = 50;
7783 if (j == 0 && Person::players[j]->num_weapons > 0) {
7784 if (weapons[Person::players[j]->weaponids[0]].bloody) {
7785 smelldistance = 100;
7787 if (Person::players[j]->num_weapons == 2) {
7788 if (weapons[Person::players[j]->weaponids[1]].bloody) {
7789 smelldistance = 100;
7794 smelldistance = 100;
7796 windsmell = windvector;
7797 Normalise(&windsmell);
7798 windsmell = windsmell * 2 + Person::players[j]->coords;
7799 if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled) {
7800 aitype = attacktypecutoff;
7806 if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7807 losupdatedelay = .2;
7808 for (unsigned j = 0; j < Person::players.size(); j++) {
7809 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7810 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7811 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7812 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7813 if ((-1 == Object::checkcollide(
7814 DoRotation(jointPos(head), 0, yaw, 0) *
7817 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0) *
7818 Person::players[j]->scale +
7819 Person::players[j]->coords) &&
7820 !Person::players[j]->isWallJump()) ||
7821 (Person::players[j]->animTarget == hanganim &&
7822 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7824 if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight) {
7833 if (lastseentime <= 0) {
7834 aitype = searchtype;
7836 lastseen = Person::players[j]->coords;
7844 if (aitype == attacktypecutoff && Game::musictype != 2) {
7845 if (creature != wolftype) {
7849 if (creature == wolftype) {
7859 if (aitype == searchtype) {
7860 aiupdatedelay -= multiplier;
7861 losupdatedelay -= multiplier;
7863 lastseentime -= multiplier;
7865 lastchecktime -= multiplier;
7867 if (isRun() && !onground) {
7868 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7869 XYZ test2 = coords + facing;
7871 XYZ test = coords + facing;
7873 j = Object::checkcollide(test2, test, laststanding);
7875 j = Object::checkcollide(test2, test);
7879 setTargetAnimation(getStop());
7882 //aitype=passivetype;
7883 aitype = pathfindtype;
7884 finalfinaltarget = waypoints[waypoint];
7885 finalpathfindpoint = -1;
7886 targetpathfindpoint = -1;
7887 lastpathfindpoint = -1;
7888 lastpathfindpoint2 = -1;
7889 lastpathfindpoint3 = -1;
7890 lastpathfindpoint4 = -1;
7896 //check out last seen location
7897 if (aiupdatedelay < 0) {
7898 targetyaw = roughDirectionTo(coords, lastseen);
7899 lookyaw = targetyaw;
7900 aiupdatedelay = .05;
7903 if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) {
7906 lastseen.x += (float(Random() % 100) - 50) / 25;
7907 lastseen.z += (float(Random() % 100) - 50) / 25;
7918 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7919 if (!avoidsomething) {
7920 targetyaw += 90 * (whichdirection * 2 - 1);
7922 XYZ leftpos, rightpos;
7923 float leftdist, rightdist;
7924 leftpos = coords + DoRotation(facing, 0, 90, 0);
7925 rightpos = coords - DoRotation(facing, 0, 90, 0);
7926 leftdist = distsq(&leftpos, &avoidwhere);
7927 rightdist = distsq(&rightpos, &avoidwhere);
7928 if (leftdist < rightdist) {
7936 if (collided < 1 || animTarget != jumpupanim) {
7939 if ((collided > .8 && jumppower >= 5)) {
7943 if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile)) {
7944 for (int k = 0; k < numenvsounds; k++) {
7945 if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) {
7946 aitype = attacktypecutoff;
7951 if (!Person::players[0]->dead &&
7952 losupdatedelay < 0 &&
7953 !Game::editorenabled &&
7955 ((!Tutorial::active || cananger) && hostile)) {
7956 losupdatedelay = .2;
7957 if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) {
7958 aitype = attacktypecutoff;
7961 if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight) {
7962 //TODO: factor out canSeePlayer()
7963 if (distsq(&coords, &Person::players[0]->coords) < 400) {
7964 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
7965 if ((Object::checkcollide(
7966 DoRotation(jointPos(head), 0, yaw, 0) *
7969 DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0) *
7970 Person::players[0]->scale +
7971 Person::players[0]->coords) == -1) ||
7972 (Person::players[0]->animTarget == hanganim && normaldotproduct(Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) {
7973 /* //TODO: changed j to 0 on a whim, make sure this is correct
7974 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
7975 Person::players[j]->facing,coords-Person::players[j]->coords)<0)
7977 aitype = attacktypecutoff;
7985 if (lastseentime < 0) {
7986 //aitype=passivetype;
7988 aitype = pathfindtype;
7989 finalfinaltarget = waypoints[waypoint];
7990 finalpathfindpoint = -1;
7991 targetpathfindpoint = -1;
7992 lastpathfindpoint = -1;
7993 lastpathfindpoint2 = -1;
7994 lastpathfindpoint3 = -1;
7995 lastpathfindpoint4 = -1;
7999 if (aitype != gethelptype) {
8003 //get help from buddies
8004 if (aitype == gethelptype) {
8005 runninghowlong += multiplier;
8006 aiupdatedelay -= multiplier;
8008 if (aiupdatedelay < 0 || ally == 0) {
8012 //TODO: factor out closest search somehow
8015 float closestdist = -1;
8016 for (unsigned k = 0; k < Person::players.size(); k++) {
8017 if ((k != id) && (k != 0) && !Person::players[k]->dead &&
8018 (Person::players[k]->howactive < typedead1) &&
8019 !Person::players[k]->skeleton.free &&
8020 (Person::players[k]->aitype == passivetype)) {
8021 float distance = distsq(&coords, &Person::players[k]->coords);
8022 if (closestdist == -1 || distance < closestdist) {
8023 closestdist = distance;
8028 if (closest != -1) {
8033 lastseen = Person::players[0]->coords;
8039 XYZ facing = coords;
8040 XYZ flatfacing = Person::players[ally]->coords;
8041 facing.y += jointPos(head).y * scale;
8042 flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale;
8043 if (-1 != Object::checkcollide(facing, flatfacing)) {
8047 //no available ally, run back to player
8049 Person::players[ally]->skeleton.free ||
8050 Person::players[ally]->aitype != passivetype ||
8051 lastseentime <= 0) {
8052 aitype = searchtype;
8058 targetyaw = roughDirectionTo(coords, Person::players[ally]->coords);
8059 lookyaw = targetyaw;
8060 aiupdatedelay = .05;
8063 if (distsqflat(&coords, &Person::players[ally]->coords) < 3) {
8064 aitype = searchtype;
8066 Person::players[ally]->aitype = searchtype;
8067 if (Person::players[ally]->lastseentime < lastseentime) {
8068 Person::players[ally]->lastseen = lastseen;
8069 Person::players[ally]->lastseentime = lastseentime;
8070 Person::players[ally]->lastchecktime = lastchecktime;
8074 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8075 if (!avoidsomething) {
8076 targetyaw += 90 * (whichdirection * 2 - 1);
8078 XYZ leftpos, rightpos;
8079 float leftdist, rightdist;
8080 leftpos = coords + DoRotation(facing, 0, 90, 0);
8081 rightpos = coords - DoRotation(facing, 0, 90, 0);
8082 leftdist = distsq(&leftpos, &avoidwhere);
8083 rightdist = distsq(&rightpos, &avoidwhere);
8084 if (leftdist < rightdist) {
8099 if (collided < 1 || animTarget != jumpupanim) {
8102 if (collided > .8 && jumppower >= 5) {
8107 //retreiving a weapon on the ground
8108 if (aitype == getweapontype) {
8109 aiupdatedelay -= multiplier;
8110 lastchecktime -= multiplier;
8112 if (aiupdatedelay < 0) {
8118 float closestdist = -1;
8119 for (unsigned k = 0; k < weapons.size(); k++) {
8120 if (weapons[k].owner == -1) {
8121 float distance = distsq(&coords, &weapons[k].position);
8122 if (closestdist == -1 || distance < closestdist) {
8123 closestdist = distance;
8128 if (closest != -1) {
8137 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile)) {
8138 if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) {
8139 aitype = attacktypecutoff;
8143 if (!Person::players[0]->dead) {
8145 if (weapons[ally].owner != -1 ||
8146 distsq(&coords, &weapons[ally].position) > 16) {
8147 aitype = attacktypecutoff;
8150 //TODO: factor these out as moveToward()
8151 targetyaw = roughDirectionTo(coords, weapons[ally].position);
8152 lookyaw = targetyaw;
8153 aiupdatedelay = .05;
8156 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8157 if (!avoidsomething) {
8158 targetyaw += 90 * (whichdirection * 2 - 1);
8160 XYZ leftpos, rightpos;
8161 float leftdist, rightdist;
8162 leftpos = coords + DoRotation(facing, 0, 90, 0);
8163 rightpos = coords - DoRotation(facing, 0, 90, 0);
8164 leftdist = distsq(&leftpos, &avoidwhere);
8165 rightdist = distsq(&rightpos, &avoidwhere);
8166 if (leftdist < rightdist) {
8182 if (animTarget != crouchremoveknifeanim &&
8183 animTarget != removeknifeanim) {
8184 throwtogglekeydown = 0;
8188 if (collided < 1 || animTarget != jumpupanim) {
8191 if ((collided > .8 && jumppower >= 5)) {
8196 if (aitype == attacktypecutoff) {
8197 aiupdatedelay -= multiplier;
8198 //dodge or reverse rabbit kicks, knife throws, flips
8199 if (damage < damagetolerance * 2 / 3) {
8200 if ((Person::players[0]->animTarget == rabbitkickanim ||
8201 Person::players[0]->animTarget == knifethrowanim ||
8202 (Person::players[0]->isFlip() &&
8203 normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) &&
8204 !Person::players[0]->skeleton.free &&
8205 (aiupdatedelay < .1)) {
8210 if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
8211 if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
8212 if (isIdle() || isCrouch() || isRun() || isFlip()) {
8213 if (abs(Random() % 2) == 0) {
8214 setTargetAnimation(backhandspringanim);
8216 setTargetAnimation(rollanim);
8218 targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
8221 if (animTarget == jumpupanim || animTarget == jumpdownanim) {
8222 setTargetAnimation(flipanim);
8227 aiupdatedelay = .02;
8230 //get confused by flips
8231 if (Person::players[0]->isFlip() &&
8232 !Person::players[0]->skeleton.free &&
8233 Person::players[0]->animTarget != walljumprightkickanim &&
8234 Person::players[0]->animTarget != walljumpleftkickanim) {
8235 if (distsq(&Person::players[0]->coords, &coords) < 25) {
8236 if ((1 - damage / damagetolerance) > .5) {
8241 //go for weapon on the ground
8242 if (wentforweapon < 3) {
8243 for (unsigned k = 0; k < weapons.size(); k++) {
8244 if (creature != wolftype) {
8245 if (num_weapons == 0 &&
8246 weapons[k].owner == -1 &&
8247 weapons[k].velocity.x == 0 &&
8248 weapons[k].velocity.z == 0 &&
8249 weapons[k].velocity.y == 0) {
8250 if (distsq(&coords, &weapons[k].position) < 16) {
8253 aitype = getweapontype;
8260 //dodge/reverse walljump kicks
8261 if (damage < damagetolerance / 2) {
8262 if (Animation::animations[animTarget].height != highheight) {
8263 if (damage < damagetolerance * .5 &&
8264 ((Person::players[0]->animTarget == walljumprightkickanim ||
8265 Person::players[0]->animTarget == walljumpleftkickanim) &&
8266 ((aiupdatedelay < .15 &&
8268 (aiupdatedelay < .08 &&
8269 difficulty != 2)))) {
8274 //walked off a ledge (?)
8275 if (isRun() && !onground) {
8276 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
8277 XYZ test2 = coords + facing;
8279 XYZ test = coords + facing;
8281 j = Object::checkcollide(test2, test, laststanding);
8283 j = Object::checkcollide(test2, test);
8287 setTargetAnimation(getStop());
8290 aitype = pathfindtype;
8291 finalfinaltarget = waypoints[waypoint];
8292 finalpathfindpoint = -1;
8293 targetpathfindpoint = -1;
8294 lastpathfindpoint = -1;
8295 lastpathfindpoint2 = -1;
8296 lastpathfindpoint3 = -1;
8297 lastpathfindpoint4 = -1;
8303 //lose sight of player in the air (?)
8304 if (Person::players[0]->coords.y > coords.y + 5 &&
8305 Animation::animations[Person::players[0]->animTarget].height != highheight &&
8306 !Person::players[0]->onterrain) {
8307 aitype = pathfindtype;
8308 finalfinaltarget = waypoints[waypoint];
8309 finalpathfindpoint = -1;
8310 targetpathfindpoint = -1;
8311 lastpathfindpoint = -1;
8312 lastpathfindpoint2 = -1;
8313 lastpathfindpoint3 = -1;
8314 lastpathfindpoint4 = -1;
8316 //it's time to think (?)
8317 if (aiupdatedelay < 0 &&
8318 !Animation::animations[animTarget].attack &&
8319 animTarget != staggerbackhighanim &&
8320 animTarget != staggerbackhardanim &&
8321 animTarget != backhandspringanim &&
8322 animTarget != dodgebackanim) {
8324 if (weaponactive == -1 && num_weapons > 0) {
8325 drawkeydown = Random() % 2;
8329 rabbitkickenabled = Random() % 2;
8331 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
8332 XYZ targetpoint = Person::players[0]->coords;
8333 float vellength = findLength(&velocity);
8334 if (vellength != 0 &&
8335 distsq(&Person::players[0]->coords, &coords) < distsq(&rotatetarget, &coords)) {
8336 targetpoint += Person::players[0]->velocity *
8337 findDistance(&Person::players[0]->coords, &coords) / vellength;
8339 targetyaw = roughDirectionTo(coords, targetpoint);
8340 lookyaw = targetyaw;
8341 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
8343 if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1)) {
8345 } else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
8346 distsq(&coords, &Person::players[0]->coords) < 9) &&
8347 Person::players[0]->weaponactive != -1) {
8349 } else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0)) {
8354 //chill out around the corpse
8355 if (Person::players[0]->dead) {
8357 if (Random() % 10 == 0) {
8360 if (Random() % 100 == 0) {
8361 aitype = pathfindtype;
8362 finalfinaltarget = waypoints[waypoint];
8363 finalpathfindpoint = -1;
8364 targetpathfindpoint = -1;
8365 lastpathfindpoint = -1;
8366 lastpathfindpoint2 = -1;
8367 lastpathfindpoint3 = -1;
8368 lastpathfindpoint4 = -1;
8377 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8378 targetyaw += 90 * (whichdirection * 2 - 1);
8381 if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype) {
8386 if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7) {
8391 if (aitype != playercontrolled &&
8396 for (unsigned j = 0; j < Person::players.size(); j++) {
8397 if (j != id && !Person::players[j]->skeleton.free &&
8398 Person::players[j]->hasvictim &&
8399 (Tutorial::active && reversaltrain ||
8400 Random() % 2 == 0 && difficulty == 2 ||
8401 Random() % 4 == 0 && difficulty == 1 ||
8402 Random() % 8 == 0 && difficulty == 0 ||
8403 Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
8404 Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
8405 (Random() % 2 == 0 || difficulty == 2) ||
8406 (isIdle() || isRun()) &&
8407 Person::players[j]->weaponactive != -1 ||
8408 Person::players[j]->animTarget == swordslashanim &&
8409 weaponactive != -1 ||
8410 Person::players[j]->animTarget == staffhitanim ||
8411 Person::players[j]->animTarget == staffspinhitanim)) {
8412 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
8413 Person::players[j]->victim == Person::players[id] &&
8414 (Person::players[j]->animTarget == sweepanim ||
8415 Person::players[j]->animTarget == spinkickanim ||
8416 Person::players[j]->animTarget == staffhitanim ||
8417 Person::players[j]->animTarget == staffspinhitanim ||
8418 Person::players[j]->animTarget == winduppunchanim ||
8419 Person::players[j]->animTarget == upunchanim ||
8420 Person::players[j]->animTarget == wolfslapanim ||
8421 Person::players[j]->animTarget == knifeslashstartanim ||
8422 Person::players[j]->animTarget == swordslashanim &&
8423 (distsq(&Person::players[j]->coords, &coords) < 2 ||
8424 weaponactive != -1))) {
8434 Person::players[target]->Reverse();
8441 if (collided > .8 && jumppower >= 5 ||
8442 distsq(&coords, &Person::players[0]->coords) > 400 &&
8444 creature == rabbittype) {
8447 //TODO: why are we controlling the human?
8448 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
8449 Person::players[0]->jumpkeydown = 0;
8451 if (Person::players[0]->animTarget == jumpdownanim &&
8452 distsq(&Person::players[0]->coords, &coords) < 40) {
8459 if (Tutorial::active) {
8465 XYZ facing = coords;
8466 XYZ flatfacing = Person::players[0]->coords;
8467 facing.y += jointPos(head).y * scale;
8468 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
8469 if (occluded >= 2) {
8470 if (-1 != Object::checkcollide(facing, flatfacing)) {
8474 if (lastseentime <= 0 &&
8475 (creature != wolftype ||
8476 weaponstuck == -1)) {
8477 aitype = searchtype;
8479 lastseen = Person::players[0]->coords;
8488 if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
8489 (aitype == attacktypecutoff ||
8490 aitype == searchtype)) {
8491 if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
8492 XYZ test = Person::players[0]->coords;
8494 if (-1 == Object::checkcollide(Person::players[0]->coords, test)) {
8500 if (aitype == passivetype && !(numwaypoints > 1) ||
8502 pause && damage > superpermanentdamage) {
8521 XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0);
8522 facing = flatfacing;
8524 if (aitype == attacktypecutoff) {
8525 targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
8526 targetheadpitch = pitchTo(coords, Person::players[0]->coords);
8527 } else if (howactive >= typesleeping) {
8528 targetheadyaw = targetyaw;
8529 targetheadpitch = 0;
8531 if (interestdelay <= 0) {
8532 interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
8533 headtarget = coords;
8534 headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
8535 headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
8536 headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
8537 headtarget += facing * 1.5;
8539 targetheadyaw = 180 - roughDirectionTo(coords, headtarget);
8540 targetheadpitch = pitchTo(coords, headtarget);