2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2017 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
21 #include "Objects/Person.hpp"
23 #include "Animation/Animation.hpp"
24 #include "Audio/Sounds.hpp"
25 #include "Audio/openal_wrapper.hpp"
27 #include "Level/Awards.hpp"
28 #include "Level/Dialog.hpp"
29 #include "Tutorial.hpp"
30 #include "Utils/Folders.hpp"
32 extern float multiplier;
33 extern Terrain terrain;
35 extern int environment;
37 extern FRUSTUM frustum;
39 extern float realmultiplier;
41 extern float slomodelay;
42 extern bool cellophane;
43 extern float texdetail;
44 extern float realtexdetail;
45 extern GLubyte bloodText[512 * 512 * 3];
46 extern GLubyte wolfbloodText[512 * 512 * 3];
47 extern int bloodtoggle;
48 extern bool autoslomo;
49 extern float camerashake;
51 extern float viewdistance;
52 extern float blackout;
53 extern int difficulty;
54 extern bool decalstoggle;
55 extern float fadestart;
57 extern bool winfreeze;
58 extern bool showpoints;
59 extern bool immediate;
60 extern float smoketex;
61 extern bool reversaltrain;
62 extern bool canattack;
64 extern float damagedealt;
66 extern float hostiletime;
68 extern bool gamestarted;
70 extern XYZ envsound[30];
71 extern float envsoundvol[30];
72 extern int numenvsounds;
73 extern float envsoundlife[30];
75 extern XYZ windvector;
77 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
78 std::vector<PersonType> PersonType::types;
80 void PersonType::Load()
85 types[wolftype].proportions[0] = 1.1;
86 types[wolftype].proportions[1] = 1.1;
87 types[wolftype].proportions[2] = 1.1;
88 types[wolftype].proportions[3] = 1.1;
90 types[wolftype].animRun = wolfrunanim;
91 types[wolftype].animRunning = wolfrunninganim;
92 types[wolftype].animCrouch = wolfcrouchanim;
93 types[wolftype].animStop = wolfstopanim;
94 types[wolftype].animLanding = wolflandanim;
95 types[wolftype].animLandingHard = wolflandhardanim;
97 types[wolftype].soundsAttack[0] = barksound;
98 types[wolftype].soundsAttack[1] = bark2sound;
99 types[wolftype].soundsAttack[2] = bark3sound;
100 types[wolftype].soundsAttack[3] = barkgrowlsound;
101 types[wolftype].soundsTalk[0] = growlsound;
102 types[wolftype].soundsTalk[1] = growl2sound;
104 types[wolftype].figureFileName = "Skeleton/BasicFigureWolf";
105 types[wolftype].lowFigureFileName = "Skeleton/BasicFigureWolfLow";
106 types[wolftype].clothesFileName = "Skeleton/RabbitBelt";
107 types[wolftype].modelFileNames[0] = "Models/Wolf.solid";
108 types[wolftype].modelFileNames[1] = "Models/Wolf2.solid";
109 types[wolftype].modelFileNames[2] = "Models/Wolf3.solid";
110 types[wolftype].modelFileNames[3] = "Models/Wolf4.solid";
111 types[wolftype].modelFileNames[4] = "Models/Wolf5.solid";
112 types[wolftype].modelFileNames[5] = "Models/Wolf6.solid";
113 types[wolftype].modelFileNames[6] = "Models/Wolf7.solid";
114 types[wolftype].lowModelFileName = "Models/WolfLow.solid";
115 types[wolftype].modelClothesFileName = "Models/Belt.solid";
117 types[wolftype].skins.resize(3);
118 types[wolftype].skins[0] = "Textures/Wolf.jpg";
119 types[wolftype].skins[1] = "Textures/DarkWolf.jpg";
120 types[wolftype].skins[2] = "Textures/SnowWolf.jpg";
123 types[rabbittype].proportions[0] = 1.2;
124 types[rabbittype].proportions[1] = 1.05;
125 types[rabbittype].proportions[2] = 1;
126 types[rabbittype].proportions[3] = 1.1;
127 types[rabbittype].proportions[3].y = 1.05;
129 types[rabbittype].animRun = runanim;
130 types[rabbittype].animRunning = rabbitrunninganim;
131 types[rabbittype].animCrouch = crouchanim;
132 types[rabbittype].animStop = stopanim;
133 types[rabbittype].animLanding = landanim;
134 types[rabbittype].animLandingHard = landhardanim;
136 types[rabbittype].soundsAttack[0] = rabbitattacksound;
137 types[rabbittype].soundsAttack[1] = rabbitattack2sound;
138 types[rabbittype].soundsAttack[2] = rabbitattack3sound;
139 types[rabbittype].soundsAttack[3] = rabbitattack4sound;
140 types[rabbittype].soundsTalk[0] = rabbitchitter;
141 types[rabbittype].soundsTalk[1] = rabbitchitter2;
143 types[rabbittype].figureFileName = "Skeleton/BasicFigure";
144 types[rabbittype].lowFigureFileName = "Skeleton/BasicFigureLow";
145 types[rabbittype].clothesFileName = "Skeleton/RabbitBelt";
146 types[rabbittype].modelFileNames[0] = "Models/Body.solid";
147 types[rabbittype].modelFileNames[1] = "Models/Body2.solid";
148 types[rabbittype].modelFileNames[2] = "Models/Body3.solid";
149 types[rabbittype].modelFileNames[3] = "Models/Body4.solid";
150 types[rabbittype].modelFileNames[4] = "Models/Body5.solid";
151 types[rabbittype].modelFileNames[5] = "Models/Body6.solid";
152 types[rabbittype].modelFileNames[6] = "Models/Body7.solid";
153 types[rabbittype].lowModelFileName = "Models/BodyLow.solid";
154 types[rabbittype].modelClothesFileName = "Models/Belt.solid";
156 types[rabbittype].skins.resize(10);
157 types[rabbittype].skins[0] = "Textures/Fur3.jpg";
158 types[rabbittype].skins[1] = "Textures/Fur.jpg";
159 types[rabbittype].skins[2] = "Textures/Fur2.jpg";
160 types[rabbittype].skins[3] = "Textures/Lynx.jpg";
161 types[rabbittype].skins[4] = "Textures/Otter.jpg";
162 types[rabbittype].skins[5] = "Textures/Opal.jpg";
163 types[rabbittype].skins[6] = "Textures/Sable.jpg";
164 types[rabbittype].skins[7] = "Textures/Chocolate.jpg";
165 types[rabbittype].skins[8] = "Textures/BW2.jpg";
166 types[rabbittype].skins[9] = "Textures/WB2.jpg";
172 , animCurrent(bounceidleanim)
173 , animTarget(bounceidleanim)
180 , howactive(typeactive)
182 , superruntoggle(false)
216 , rabbitkickenabled(false)
230 , superpermanentdamage(0)
273 , normalsupdatedelay(0)
277 , forwardkeydown(false)
278 , forwardstogglekeydown(false)
279 , rightkeydown(false)
283 , jumptogglekeydown(false)
284 , crouchkeydown(false)
285 , crouchtogglekeydown(false)
287 , drawtogglekeydown(false)
288 , throwkeydown(false)
289 , throwtogglekeydown(false)
290 , attackkeydown(false)
312 , whichdirection(false)
313 , whichdirectiondelay(0)
314 , avoidsomething(false)
324 , lefthandmorphness(0)
325 , righthandmorphness(0)
329 , targetlefthandmorphness(0)
330 , targetrighthandmorphness(0)
331 , targetheadmorphness(1)
332 , targetchestmorphness(0)
333 , targettailmorphness(0)
334 , lefthandmorphstart(0)
335 , lefthandmorphend(0)
336 , righthandmorphstart(0)
337 , righthandmorphend(0)
347 , highreversaldelay(0)
348 , lowreversaldelay(0)
397 , weaponstuckwhere(0)
410 , finalpathfindpoint(0)
411 , targetpathfindpoint(0)
412 , lastpathfindpoint(0)
413 , lastpathfindpoint2(0)
414 , lastpathfindpoint3(0)
415 , lastpathfindpoint4(0)
435 , neckspurtparticledelay(0)
440 , rabbitkickragdoll(false)
448 setProportions(1, 1, 1, 1);
451 /* Read a person in tfile. Throws an error if it’s not valid */
452 Person::Person(FILE* tfile, int mapvers, unsigned i)
456 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
458 funpackf(tfile, "Bi", &howactive);
460 howactive = typeactive;
463 funpackf(tfile, "Bf", &scale);
468 funpackf(tfile, "Bb", &immobile);
473 funpackf(tfile, "Bf", &yaw);
478 if (num_weapons < 0 || num_weapons > 5) {
479 throw InvalidPersonException();
481 if (num_weapons > 0 && num_weapons < 5) {
482 for (int j = 0; j < num_weapons; j++) {
483 weaponids[j] = weapons.size();
485 funpackf(tfile, "Bi", &type);
486 weapons.push_back(Weapon(type, id));
489 funpackf(tfile, "Bi", &numwaypoints);
490 for (int j = 0; j < numwaypoints; j++) {
491 funpackf(tfile, "Bf", &waypoints[j].x);
492 funpackf(tfile, "Bf", &waypoints[j].y);
493 funpackf(tfile, "Bf", &waypoints[j].z);
495 funpackf(tfile, "Bi", &waypointtype[j]);
497 waypointtype[j] = wpkeepwalking;
501 funpackf(tfile, "Bi", &waypoint);
502 if (waypoint > (numwaypoints - 1)) {
506 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
507 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
508 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
509 funpackf(tfile, "Bf Bf", &power, &speedmult);
512 funpackf(tfile, "Bf Bf Bf Bf", &proportions[0], &proportions[1], &proportions[2], &proportions[3]);
514 setProportions(1, 1, 1, 1);
517 funpackf(tfile, "Bi", &numclothes);
518 for (int k = 0; k < numclothes; k++) {
520 funpackf(tfile, "Bi", &templength);
521 for (int l = 0; l < templength; l++) {
522 funpackf(tfile, "Bb", &clothes[k][l]);
524 clothes[k][templength] = '\0';
525 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
531 if (creature == wolftype) {
533 damagetolerance = 300;
540 realoldcoords = coords;
543 void Person::skeletonLoad(bool clothes)
547 PersonType::types[creature].figureFileName,
548 PersonType::types[creature].lowFigureFileName,
549 PersonType::types[creature].clothesFileName,
550 PersonType::types[creature].modelFileNames[0],
551 PersonType::types[creature].modelFileNames[1],
552 PersonType::types[creature].modelFileNames[2],
553 PersonType::types[creature].modelFileNames[3],
554 PersonType::types[creature].modelFileNames[4],
555 PersonType::types[creature].modelFileNames[5],
556 PersonType::types[creature].modelFileNames[6],
557 PersonType::types[creature].lowModelFileName,
558 PersonType::types[creature].modelClothesFileName,
561 skeleton.drawmodel.textureptr.load(PersonType::types[creature].skins[whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
564 void Person::setProportions(float head, float body, float arms, float legs)
566 proportions[0] = head;
567 proportions[1] = body;
568 proportions[2] = arms;
569 proportions[3] = legs;
572 XYZ Person::getProportion(int part) const
574 XYZ prop = PersonType::types[creature].proportions[part] * proportions[part];
584 * GameTick/doPlayerCollisions
586 void Person::CheckKick()
588 if (!(hasvictim && (animTarget == rabbitkickanim && victim && victim != this->shared_from_this() && frameCurrent >= 2 && animCurrent == rabbitkickanim) && distsq(&coords, &victim->coords) < 1.2 && !victim->skeleton.free)) {
592 if (Animation::animations[victim->animTarget].height != lowheight) {
593 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
594 XYZ relative = velocity;
596 Normalise(&relative);
600 if (!Tutorial::active) {
601 emit_sound_at(heavyimpactsound, victim->coords);
604 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
605 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
608 victim->DoDamage(100 * damagemult / victim->protectionhigh);
615 animTarget = backflipanim;
617 velocity = facing * -10;
621 resume_stream(whooshsound);
624 award_bonus(id, cannon);
625 } else if (victim->isCrouch()) {
626 animTarget = rabbitkickreversedanim;
627 animCurrent = rabbitkickreversedanim;
628 victim->animCurrent = rabbitkickreversalanim;
629 victim->animTarget = rabbitkickreversalanim;
635 victim->oldcoords = victim->coords;
636 coords = victim->coords;
637 victim->targetyaw = targetyaw;
638 victim->victim = this->shared_from_this();
645 * GameTick::doPlayerCollisions - spread fire between players
646 * GameTick::ProcessDevKeys - press f to ignite
647 * Person::DoStuff - spread fire from lit campfires and bushes
649 void Person::CatchFire()
651 XYZ flatfacing, flatvelocity;
653 for (int i = 0; i < 10; i++) {
654 howmany = fabs(Random() % (skeleton.joints.size()));
656 flatvelocity = skeleton.joints[howmany].velocity;
657 flatfacing = skeleton.joints[howmany].position * scale + coords;
659 flatvelocity = velocity;
660 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
662 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
667 emit_sound_at(firestartsound, coords);
669 emit_stream_at(stream_firesound, coords);
677 * idle animation for this creature (depending on status)
679 int Person::getIdle()
681 if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype)) {
684 if (hasvictim && (victim != this->shared_from_this())) {
685 if ((!victim->dead && victim->aitype != passivetype &&
686 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
687 victim->id < Person::players.size())) {
688 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
689 if (creature == rabbittype) {
690 return fightidleanim;
692 if (creature == wolftype) {
696 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
697 if (weapons[weaponids[weaponactive]].getType() == knife) {
698 return knifefightidleanim;
700 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1) {
701 return swordfightidlebothanim;
703 if (weapons[weaponids[weaponactive]].getType() == sword) {
704 return swordfightidleanim;
706 if (weapons[weaponids[weaponactive]].getType() == staff) {
707 return swordfightidleanim;
710 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause) {
711 return fightsidestep;
715 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype) {
718 if (howactive == typesitting) {
721 if (howactive == typesittingwall) {
724 if (howactive == typesleeping) {
727 if (howactive == typedead1) {
730 if (howactive == typedead2) {
733 if (howactive == typedead3) {
736 if (howactive == typedead4) {
739 if (creature == rabbittype) {
740 return bounceidleanim;
742 if (creature == wolftype) {
749 * crouch animation for this creature
751 int Person::getCrouch()
753 return PersonType::types[creature].animCrouch;
757 * running animation for this creature (can be upright or all fours)
761 if (superruntoggle && (weaponactive == -1)) {
762 return PersonType::types[creature].animRunning;
764 return PersonType::types[creature].animRun;
770 int Person::getStop()
772 return PersonType::types[creature].animStop;
777 int Person::getLanding()
779 return PersonType::types[creature].animLanding;
784 int Person::getLandhard()
786 return PersonType::types[creature].animLandingHard;
792 * Person::DoAnimations
795 SolidHitBonus(int playerid)
797 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo) {
798 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
800 award_bonus(playerid, solidhit);
805 * spawns blood effects
807 void Person::DoBlood(float howmuch, int which)
809 // FIXME: should abstract out inputs
810 static int bleedxint, bleedyint;
812 if (bloodtoggle && !Tutorial::active) {
813 if (bleeding <= 0 && spurt) {
815 for (int i = 0; i < 3; i++) {
816 // emit blood particles
819 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
820 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
821 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
822 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
825 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
826 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
827 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
828 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
831 if (Random() % 2 == 0) { // 50% chance
832 for (int i = 0; i < 3; i++) {
833 if (Random() % 2 != 0) {
834 // emit teeth particles
837 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
838 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
841 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
842 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
846 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
848 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
850 Sprite::setLastSpriteSpecial(3); // sets it to teeth
856 // FIXME: manipulating attributes
857 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
860 if (creature == rabbittype) {
861 while (bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
862 bleedxint = abs(Random() % 512);
863 bleedyint = abs(Random() % 512);
866 if (creature == wolftype) {
867 while (wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
868 bleedxint = abs(Random() % 512);
869 bleedyint = abs(Random() % 512);
874 bleedy /= realtexdetail;
875 bleedx /= realtexdetail;
876 direction = abs(Random() % 2) * 2 - 1;
885 * spawns big blood effects and ???
886 * modifies character's skin texture
888 void Person::DoBloodBig(float howmuch, int which)
890 static int bleedxint, bleedyint, i, j;
892 if (howmuch && id == 0) {
896 if (!Tutorial::active || id == 0) {
897 if (aitype != playercontrolled && howmuch > 0) {
901 if (creature == wolftype) {
902 int i = abs(Random() % 2);
904 whichsound = snarlsound;
907 whichsound = snarl2sound;
910 if (creature == rabbittype) {
911 int i = abs(Random() % 2);
913 whichsound = rabbitpainsound;
915 if (i == 1 && howmuch >= 2) {
916 whichsound = rabbitpain1sound;
920 if (whichsound != -1) {
921 emit_sound_at(whichsound, coords);
927 if (id == 0 && howmuch > 0) {
931 if (bloodtoggle && decalstoggle && !Tutorial::active) {
932 if (bleeding <= 0 && spurt) {
934 for (int i = 0; i < 3; i++) {
935 // emit blood particles
936 // FIXME: copypaste from above
939 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
940 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
941 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
942 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
945 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
946 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
947 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
948 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
953 // weird texture manipulation code follows.
954 // looks like this is painting blood onto the character's skin texture
955 // FIXME: surely there's a better way
957 int offsetx = 0, offsety = 0;
959 offsety = Random() % 40;
960 offsetx = abs(Random() % 60);
962 if (which == 190 || which == 185) {
963 offsety = Random() % 40;
964 offsetx = abs(Random() % 100) - 20;
967 offsety = Random() % 10;
968 offsetx = Random() % 10;
971 offsety = Random() % 20;
972 offsetx = Random() % 20;
974 if (which == 220 || which == 215) {
983 if (creature == rabbittype) {
984 for (i = 0; i < 512; i++) {
985 for (j = 0; j < 512; j++) {
986 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1003 if (creature == wolftype) {
1004 for (i = 0; i < 512; i++) {
1005 for (j = 0; j < 512; j++) {
1006 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1035 if (endx > 512 - 1) {
1038 if (endy > 512 - 1) {
1041 if (endx < startx) {
1044 if (endy < starty) {
1048 startx /= realtexdetail;
1049 starty /= realtexdetail;
1050 endx /= realtexdetail;
1051 endy /= realtexdetail;
1053 int texdetailint = realtexdetail;
1055 if (creature == rabbittype) {
1056 for (i = startx; i < endx; i++) {
1057 for (j = starty; j < endy; j++) {
1058 if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
1059 color = Random() % 85 + 170;
1060 where = i * skeleton.skinsize * 3 + j * 3;
1061 if (skeleton.skinText[where + 0] > color / 2) {
1062 skeleton.skinText[where + 0] = color / 2;
1064 skeleton.skinText[where + 1] = 0;
1065 skeleton.skinText[where + 2] = 0;
1070 if (creature == wolftype) {
1071 for (i = startx; i < endx; i++) {
1072 for (j = starty; j < endy; j++) {
1073 if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
1074 color = Random() % 85 + 170;
1075 where = i * skeleton.skinsize * 3 + j * 3;
1076 if (skeleton.skinText[where + 0] > color / 2) {
1077 skeleton.skinText[where + 0] = color / 2;
1079 skeleton.skinText[where + 1] = 0;
1080 skeleton.skinText[where + 2] = 0;
1085 skeleton.drawmodel.textureptr.bind();
1090 if (creature == rabbittype) {
1091 while (bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
1092 bleedxint = abs(Random() % 512);
1093 bleedyint = abs(Random() % 512);
1096 if (creature == wolftype) {
1097 while (wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
1098 bleedxint = abs(Random() % 512);
1099 bleedyint = abs(Random() % 512);
1102 bleedy = bleedxint + offsetx;
1103 bleedx = bleedyint + offsety;
1104 bleedy /= realtexdetail;
1105 bleedx /= realtexdetail;
1112 if (bleedx > skeleton.skinsize - 1) {
1113 bleedx = skeleton.skinsize - 1;
1115 if (bleedy > skeleton.skinsize - 1) {
1116 bleedy = skeleton.skinsize - 1;
1118 direction = abs(Random() % 2) * 2 - 1;
1120 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1121 deathbleeding += bleeding;
1122 bloodloss += bleeding * 3;
1124 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1125 if (abs(Random() % 2) == 0) {
1126 aitype = gethelptype;
1129 aitype = attacktypecutoff;
1139 * similar to DoBloodBig
1141 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
1144 static XYZ bloodvel;
1145 static XYZ startpoint, endpoint, colpoint, movepoint;
1146 static float rotationpoint;
1147 static int whichtri;
1148 static XYZ p1, p2, p3, p0;
1151 float coordsx, coordsy;
1154 if (bloodtoggle && decalstoggle && !Tutorial::active) {
1156 if (!skeleton.free) {
1157 where = DoRotation(where, 0, -yaw, 0);
1161 startpoint.y += 100;
1166 // ray testing for a tri in the character model
1167 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
1168 if (whichtri != -1) {
1169 // low level geometry math
1171 p1 = skeleton.drawmodel.getTriangleVertex(whichtri, 0);
1172 p2 = skeleton.drawmodel.getTriangleVertex(whichtri, 1);
1173 p3 = skeleton.drawmodel.getTriangleVertex(whichtri, 2);
1175 bary.x = distsq(&p0, &p1);
1176 bary.y = distsq(&p0, &p2);
1177 bary.z = distsq(&p0, &p3);
1179 total = bary.x + bary.y + bary.z;
1184 bary.x = 1 - bary.x;
1185 bary.y = 1 - bary.y;
1186 bary.z = 1 - bary.z;
1188 total = bary.x + bary.y + bary.z;
1193 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1194 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1195 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1196 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1197 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1198 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1199 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;
1200 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;
1202 if (bleeding <= 0 && spurt) {
1204 for (int i = 0; i < 3; i++) {
1205 // emit blood particles
1206 // FIXME: more copypaste code
1208 if (skeleton.free) {
1209 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1210 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1211 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1212 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1215 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1216 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1217 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1218 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1223 // texture manipulation follows
1225 int offsetx = 0, offsety = 0;
1226 offsetx = (1 + coordsy) * 512 - 291;
1227 offsety = coordsx * 512 - 437;
1234 if (creature == rabbittype) {
1235 for (i = 0; i < 512; i++) {
1236 for (j = 0; j < 512; j++) {
1237 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1254 if (creature == wolftype) {
1255 for (i = 0; i < 512; i++) {
1256 for (j = 0; j < 512; j++) {
1257 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1285 if (endx > 512 - 1) {
1288 if (endy > 512 - 1) {
1291 if (endx < startx) {
1294 if (endy < starty) {
1298 startx /= realtexdetail;
1299 starty /= realtexdetail;
1300 endx /= realtexdetail;
1301 endy /= realtexdetail;
1303 int texdetailint = realtexdetail;
1305 if (creature == rabbittype) {
1306 for (i = startx; i < endx; i++) {
1307 for (j = starty; j < endy; j++) {
1308 if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
1309 color = Random() % 85 + 170;
1310 where = i * skeleton.skinsize * 3 + j * 3;
1311 if (skeleton.skinText[where + 0] > color / 2) {
1312 skeleton.skinText[where + 0] = color / 2;
1314 skeleton.skinText[where + 1] = 0;
1315 skeleton.skinText[where + 2] = 0;
1316 } else if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= 160 + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= 160 - 4) {
1317 color = Random() % 85 + 170;
1318 where = i * skeleton.skinsize * 3 + j * 3;
1319 if (skeleton.skinText[where + 0] > color / 2) {
1320 skeleton.skinText[where + 0] = color / 2;
1322 skeleton.skinText[where + 1] = 0;
1323 skeleton.skinText[where + 2] = 0;
1328 if (creature == wolftype) {
1329 for (i = startx; i < endx; i++) {
1330 for (j = starty; j < endy; j++) {
1331 if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
1332 color = Random() % 85 + 170;
1333 where = i * skeleton.skinsize * 3 + j * 3;
1334 if (skeleton.skinText[where + 0] > color / 2) {
1335 skeleton.skinText[where + 0] = color / 2;
1337 skeleton.skinText[where + 1] = 0;
1338 skeleton.skinText[where + 2] = 0;
1339 } else if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= 160 + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= 160 - 4) {
1340 color = Random() % 85 + 170;
1341 where = i * skeleton.skinsize * 3 + j * 3;
1342 if (skeleton.skinText[where + 0] > color / 2) {
1343 skeleton.skinText[where + 0] = color / 2;
1345 skeleton.skinText[where + 1] = 0;
1346 skeleton.skinText[where + 2] = 0;
1351 skeleton.drawmodel.textureptr.bind();
1354 bleedy = (1 + coordsy) * 512;
1355 bleedx = coordsx * 512;
1356 bleedy /= realtexdetail;
1357 bleedx /= realtexdetail;
1364 if (bleedx > skeleton.skinsize - 1) {
1365 bleedx = skeleton.skinsize - 1;
1367 if (bleedy > skeleton.skinsize - 1) {
1368 bleedy = skeleton.skinsize - 1;
1370 direction = abs(Random() % 2) * 2 - 1;
1372 if (whichtri == -1) {
1376 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1377 deathbleeding += bleeding;
1378 bloodloss += bleeding * 3;
1380 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1381 if (abs(Random() % 2) == 0) {
1382 aitype = gethelptype;
1385 aitype = attacktypecutoff;
1396 * guessing this performs a reversal
1398 void Person::Reverse()
1400 if (!((victim->aitype == playercontrolled || hostiletime > 1 || staggerdelay <= 0) && victim->animTarget != jumpupanim && victim->animTarget != jumpdownanim && (!Tutorial::active || cananger) && hostile)) {
1404 if (normaldotproduct(victim->facing, victim->coords - coords) > 0 && (victim->id != 0 || difficulty >= 2) && (creature != wolftype || victim->creature == wolftype)) {
1408 if (animTarget == sweepanim) {
1409 animTarget = sweepreversedanim;
1410 animCurrent = sweepreversedanim;
1411 victim->animCurrent = sweepreversalanim;
1412 victim->animTarget = sweepreversalanim;
1414 if (animTarget == spinkickanim) {
1415 animTarget = spinkickreversedanim;
1416 animCurrent = spinkickreversedanim;
1417 victim->animCurrent = spinkickreversalanim;
1418 victim->animTarget = spinkickreversalanim;
1420 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1421 if (animTarget == rabbittacklinganim) {
1424 victim->frameCurrent = 6;
1425 victim->frameTarget = 7;
1427 animTarget = upunchreversedanim;
1428 animCurrent = upunchreversedanim;
1429 victim->animCurrent = upunchreversalanim;
1430 victim->animTarget = upunchreversalanim;
1432 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1433 if (victim->weaponactive != -1) {
1434 victim->throwtogglekeydown = 1;
1435 XYZ tempVelocity = victim->velocity * .2;
1436 if (tempVelocity.x == 0) {
1437 tempVelocity.x = .1;
1439 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1440 victim->num_weapons--;
1441 if (victim->num_weapons) {
1442 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1443 if (victim->weaponstuck == victim->num_weapons) {
1444 victim->weaponstuck = 0;
1448 victim->weaponactive = -1;
1449 for (unsigned j = 0; j < Person::players.size(); j++) {
1450 Person::players[j]->wentforweapon = 0;
1454 animTarget = staffhitreversedanim;
1455 animCurrent = staffhitreversedanim;
1456 victim->animCurrent = staffhitreversalanim;
1457 victim->animTarget = staffhitreversalanim;
1459 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1460 if (victim->weaponactive != -1) {
1461 victim->throwtogglekeydown = 1;
1462 XYZ tempVelocity = victim->velocity * .2;
1463 if (tempVelocity.x == 0) {
1464 tempVelocity.x = .1;
1466 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1467 victim->num_weapons--;
1468 if (victim->num_weapons) {
1469 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1470 if (victim->weaponstuck == victim->num_weapons) {
1471 victim->weaponstuck = 0;
1475 victim->weaponactive = -1;
1476 for (unsigned j = 0; j < Person::players.size(); j++) {
1477 Person::players[j]->wentforweapon = 0;
1480 animTarget = staffspinhitreversedanim;
1481 animCurrent = staffspinhitreversedanim;
1482 victim->animCurrent = staffspinhitreversalanim;
1483 victim->animTarget = staffspinhitreversalanim;
1485 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1486 if (victim->weaponactive != -1) {
1487 victim->throwtogglekeydown = 1;
1488 XYZ tempVelocity = victim->velocity * .2;
1489 if (tempVelocity.x == 0) {
1490 tempVelocity.x = .1;
1492 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1493 victim->num_weapons--;
1494 if (victim->num_weapons) {
1495 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1496 if (victim->weaponstuck == victim->num_weapons) {
1497 victim->weaponstuck = 0;
1501 victim->weaponactive = -1;
1502 for (unsigned j = 0; j < Person::players.size(); j++) {
1503 Person::players[j]->wentforweapon = 0;
1506 animTarget = swordslashreversedanim;
1507 animCurrent = swordslashreversedanim;
1508 victim->animCurrent = swordslashreversalanim;
1509 victim->animTarget = swordslashreversalanim;
1511 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1512 if (victim->weaponactive != -1) {
1513 victim->throwtogglekeydown = 1;
1514 XYZ tempVelocity = victim->velocity * .2;
1515 if (tempVelocity.x == 0) {
1516 tempVelocity.x = .1;
1518 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1519 victim->num_weapons--;
1520 if (victim->num_weapons) {
1521 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1522 if (victim->weaponstuck == victim->num_weapons) {
1523 victim->weaponstuck = 0;
1527 victim->weaponactive = -1;
1528 for (unsigned j = 0; j < Person::players.size(); j++) {
1529 Person::players[j]->wentforweapon = 0;
1532 animTarget = knifeslashreversedanim;
1533 animCurrent = knifeslashreversedanim;
1534 victim->animCurrent = knifeslashreversalanim;
1535 victim->animTarget = knifeslashreversalanim;
1537 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1538 victim->targettilt2 = targettilt2;
1539 victim->frameCurrent = frameCurrent;
1540 victim->frameTarget = frameTarget;
1541 victim->target = target;
1542 victim->velocity = 0;
1543 victim->oldcoords = victim->coords;
1544 victim->coords = coords;
1545 victim->targetyaw = targetyaw;
1546 victim->yaw = targetyaw;
1547 victim->victim = this->shared_from_this();
1549 if (animTarget == winduppunchanim) {
1550 animTarget = winduppunchblockedanim;
1551 victim->animTarget = blockhighleftanim;
1552 victim->frameTarget = 1;
1553 victim->target = .5;
1554 victim->victim = this->shared_from_this();
1555 victim->targetyaw = targetyaw + 180;
1557 if (animTarget == wolfslapanim) {
1558 animTarget = winduppunchblockedanim;
1559 victim->animTarget = blockhighleftanim;
1560 victim->frameTarget = 1;
1561 victim->target = .5;
1562 victim->victim = this->shared_from_this();
1563 victim->targetyaw = targetyaw + 180;
1565 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1566 animTarget = swordslashparriedanim;
1567 parriedrecently = .4;
1568 victim->parriedrecently = 0;
1569 victim->animTarget = swordslashparryanim;
1570 victim->frameTarget = 1;
1571 victim->target = .5;
1572 victim->victim = this->shared_from_this();
1573 victim->targetyaw = targetyaw + 180;
1575 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1576 if (victim->weaponactive != -1) {
1577 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1578 if (weapons[victim->weaponids[0]].getType() == staff) {
1579 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1581 if (weapons[weaponids[0]].getType() == staff) {
1582 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1584 emit_sound_at(swordstaffsound, victim->coords);
1586 emit_sound_at(metalhitsound, victim->coords);
1590 victim->Puff(righthand);
1592 victim->frameTarget = 0;
1593 victim->animTarget = staggerbackhighanim;
1594 victim->targetyaw = targetyaw + 180;
1596 aim = DoRotation(facing, 0, 90, 0) * 21;
1598 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1599 victim->num_weapons--;
1600 if (victim->num_weapons) {
1601 victim->weaponids[0] = victim->weaponids[num_weapons];
1602 if (victim->weaponstuck == victim->num_weapons) {
1603 victim->weaponstuck = 0;
1606 victim->weaponactive = -1;
1607 for (unsigned i = 0; i < Person::players.size(); i++) {
1608 Person::players[i]->wentforweapon = 0;
1612 if (abs(Random() % 20) == 0) {
1613 if (weaponactive != -1) {
1614 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1615 if (weapons[victim->weaponids[0]].getType() == staff) {
1616 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1618 if (weapons[weaponids[0]].getType() == staff) {
1619 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1622 emit_sound_at(swordstaffsound, coords);
1624 emit_sound_at(metalhitsound, coords);
1632 animTarget = staggerbackhighanim;
1633 targetyaw = targetyaw + 180;
1635 aim = DoRotation(facing, 0, 90, 0) * 21;
1637 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1640 weaponids[0] = weaponids[num_weapons];
1641 if (weaponstuck == num_weapons) {
1646 for (unsigned i = 0; i < Person::players.size(); i++) {
1647 Person::players[i]->wentforweapon = 0;
1652 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1653 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1654 victim->animTarget = dodgebackanim;
1655 victim->frameTarget = 0;
1659 rotatetarget = coords - victim->coords;
1660 Normalise(&rotatetarget);
1661 victim->targetyaw = -asin(0 - rotatetarget.x);
1662 victim->targetyaw *= 360 / 6.28;
1663 if (rotatetarget.z < 0) {
1664 victim->targetyaw = 180 - victim->targetyaw;
1667 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1669 victim->lastattack3 = victim->lastattack2;
1670 victim->lastattack2 = victim->lastattack;
1671 victim->lastattack = victim->animTarget;
1673 victim->animTarget = sweepanim;
1674 victim->frameTarget = 0;
1678 rotatetarget = coords - victim->coords;
1679 Normalise(&rotatetarget);
1680 victim->targetyaw = -asin(0 - rotatetarget.x);
1681 victim->targetyaw *= 360 / 6.28;
1682 if (rotatetarget.z < 0) {
1683 victim->targetyaw = 180 - victim->targetyaw;
1686 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1688 victim->lastattack3 = victim->lastattack2;
1689 victim->lastattack2 = victim->lastattack;
1690 victim->lastattack = victim->animTarget;
1696 victim->velocity = 0;
1698 if (aitype != playercontrolled) {
1700 if (escapednum < 2) {
1701 int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
1702 if ((Random() % chances) == 0) {
1708 if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal) {
1716 void Person::DoDamage(float howmuch)
1720 damagetaken += howmuch / power;
1722 damagedealt += howmuch / power;
1726 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo)) {
1731 if (!Tutorial::active) {
1732 damage += howmuch / power;
1733 permanentdamage += howmuch / 2 / power;
1734 superpermanentdamage += howmuch / 4 / power;
1737 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2) {
1740 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt) {
1745 camerashake += howmuch / 100;
1746 if ((howmuch > 50 && damage > damagetolerance / 2)) {
1747 blackout = damage / damagetolerance;
1755 if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile)) {
1756 aitype = attacktypecutoff;
1758 if (!Tutorial::active && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1759 if (abs(Random() % 2) == 0) {
1760 aitype = gethelptype;
1763 aitype = attacktypecutoff;
1768 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1771 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1772 if (skeleton.free) {
1773 flatvelocity2 = skeleton.joints[i].velocity;
1774 flatfacing2 = skeleton.joints[i].position * scale + coords;
1776 flatvelocity2 = velocity;
1777 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1779 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1780 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1781 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1782 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1783 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1784 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1787 emit_sound_at(splattersound, coords);
1792 if (!dead && creature == wolftype) {
1793 award_bonus(0, Wolfbonus);
1800 if (!Tutorial::active || id == 0) {
1801 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1802 int whichsound = -1;
1804 if (creature == wolftype) {
1805 int i = abs(Random() % 2);
1807 whichsound = snarlsound;
1810 whichsound = snarl2sound;
1813 if (creature == rabbittype) {
1814 int i = abs(Random() % 2);
1816 whichsound = rabbitpainsound;
1818 if (i == 1 && damage > damagetolerance) {
1819 whichsound = rabbitpain1sound;
1823 if (whichsound != -1) {
1824 emit_sound_at(whichsound, coords);
1825 addEnvSound(coords);
1833 * calculate/animate head facing direction?
1835 void Person::DoHead()
1837 static XYZ rotatearound;
1839 static float lookspeed = 500;
1841 if (!freeze && !winfreeze) {
1844 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1845 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1847 while (targetheadyaw > 180) {
1848 targetheadyaw -= 360;
1850 while (targetheadyaw < -180) {
1851 targetheadyaw += 360;
1854 if (targetheadyaw > 160) {
1855 targetheadpitch = targetheadpitch * -1;
1857 if (targetheadyaw < -160) {
1858 targetheadpitch = targetheadpitch * -1;
1860 if (targetheadyaw > 160) {
1861 targetheadyaw = targetheadyaw - 180;
1863 if (targetheadyaw < -160) {
1864 targetheadyaw = targetheadyaw + 180;
1867 if (targetheadpitch > 120) {
1868 targetheadpitch = 120;
1870 if (targetheadpitch < -120) {
1871 targetheadpitch = -120;
1873 if (targetheadyaw > 120) {
1874 targetheadyaw = 120;
1876 if (targetheadyaw < -120) {
1877 targetheadyaw = -120;
1881 targetheadpitch = 0;
1884 if (targetheadyaw > 80) {
1887 if (targetheadyaw < -80) {
1888 targetheadyaw = -80;
1890 if (targetheadpitch > 50) {
1891 targetheadpitch = 50;
1893 if (targetheadpitch < -50) {
1894 targetheadpitch = -50;
1898 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed) {
1899 headyaw = targetheadyaw;
1900 } else if (headyaw > targetheadyaw) {
1901 headyaw -= multiplier * lookspeed;
1902 } else if (headyaw < targetheadyaw) {
1903 headyaw += multiplier * lookspeed;
1906 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2) {
1907 headpitch = targetheadpitch;
1908 } else if (headpitch > targetheadpitch) {
1909 headpitch -= multiplier * lookspeed / 2;
1910 } else if (headpitch < targetheadpitch) {
1911 headpitch += multiplier * lookspeed / 2;
1914 rotatearound = jointPos(neck);
1915 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1919 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1920 facing = DoRotation(facing, headpitch * .4, 0, 0);
1921 facing = DoRotation(facing, 0, headyaw * .4, 0);
1924 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1925 facing = DoRotation(facing, headpitch * .8, 0, 0);
1926 facing = DoRotation(facing, 0, headyaw * .8, 0);
1929 if (animTarget == walkanim) {
1930 facing = DoRotation(facing, headpitch * .6, 0, 0);
1931 facing = DoRotation(facing, 0, headyaw * .6, 0);
1934 skeleton.specialforward[0] = facing;
1935 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1936 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
1937 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1938 skeleton.FindRotationMuscle(i, animTarget);
1945 * ragdolls character?
1947 void Person::RagDoll(bool checkcollision)
1952 if (!skeleton.free) {
1956 if (id == 0 && isFlip()) {
1964 facing = DoRotation(facing, 0, yaw, 0);
1966 skeleton.freetime = 0;
1968 skeleton.longdead = 0;
1971 skeleton.broken = 0;
1972 skeleton.spinny = 1;
1974 skeleton.freefall = 1;
1976 if (!isnormal(velocity.x)) {
1979 if (!isnormal(velocity.y)) {
1982 if (!isnormal(velocity.z)) {
1985 if (!isnormal(yaw)) {
1988 if (!isnormal(coords.x)) {
1991 if (!isnormal(tilt)) {
1994 if (!isnormal(tilt2)) {
1998 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1999 skeleton.joints[i].delay = 0;
2000 skeleton.joints[i].locked = 0;
2001 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
2002 if (!isnormal(skeleton.joints[i].position.x)) {
2003 skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
2005 if (!isnormal(skeleton.joints[i].position.x)) {
2006 skeleton.joints[i].position = coords;
2008 skeleton.joints[i].position.y += .1;
2009 skeleton.joints[i].oldposition = skeleton.joints[i].position;
2010 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
2013 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
2014 skeleton.joints[i].velocity = 0;
2015 skeleton.joints[i].velchange = 0;
2017 skeleton.DoConstraints(&coords, &scale);
2018 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
2019 skeleton.DoConstraints(&coords, &scale);
2020 skeleton.DoConstraints(&coords, &scale);
2021 skeleton.DoConstraints(&coords, &scale);
2022 skeleton.DoConstraints(&coords, &scale);
2025 speed = targetFrame().speed * 2;
2026 if (currentFrame().speed > targetFrame().speed) {
2027 speed = currentFrame().speed * 2;
2030 speed = transspeed * 2;
2035 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
2036 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height) {
2037 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);
2039 skeleton.joints[i].velocity = velocity / scale + facing * 5;
2041 change.x = (float)(Random() % 100) / 100;
2042 change.y = (float)(Random() % 100) / 100;
2043 change.z = (float)(Random() % 100) / 100;
2044 skeleton.joints[i].velocity += change;
2045 skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change;
2047 change.x = (float)(Random() % 100) / 100;
2048 change.y = (float)(Random() % 100) / 100;
2049 change.z = (float)(Random() % 100) / 100;
2050 skeleton.joints[i].velchange += change;
2051 skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change;
2054 if (checkcollision) {
2057 if (!skeleton.joints.empty()) {
2060 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
2061 average += skeleton.joints[j].position;
2063 average /= skeleton.joints.size();
2064 coords += average * scale;
2065 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
2066 skeleton.joints[j].position -= average;
2070 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
2071 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
2072 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
2073 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
2076 if (SphereCheck(&lowpoint, 3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
2077 coords.x = lowpoint.x;
2078 coords.z = lowpoint.z;
2087 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
2088 velocity += skeleton.joints[i].velocity * scale;
2090 velocity /= skeleton.joints.size();
2093 if (Random() % 2 == 0) {
2094 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
2095 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
2096 weapons[weaponids[0]].velocity.x += .01;
2099 weaponids[0] = weaponids[num_weapons];
2100 if (weaponstuck == num_weapons) {
2105 for (unsigned i = 0; i < Person::players.size(); i++) {
2106 Person::players[i]->wentforweapon = 0;
2111 animTarget = bounceidleanim;
2112 animCurrent = bounceidleanim;
2120 void Person::FootLand(bodypart whichfoot, float opacity)
2122 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
2123 cerr << "FootLand called on wrong bodypart" << endl;
2126 static XYZ terrainlight;
2127 static XYZ footvel, footpoint;
2128 if (opacity >= 1 || skiddelay <= 0) {
2131 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2132 if (distsq(&footpoint, &viewer)) {
2133 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
2135 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
2136 footvel = velocity / 5;
2137 if (footvel.y < .8) {
2140 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2141 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
2142 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
2143 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
2144 if (environment == snowyenvironment) {
2145 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
2147 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
2149 } else if (environment == grassyenvironment) {
2150 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
2151 } else if (environment == desertenvironment) {
2152 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
2154 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
2158 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
2159 footvel = velocity / 5;
2160 if (footvel.y < .8) {
2163 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2164 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
2165 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
2172 * make a puff effect at a body part (dust effect?)
2174 void Person::Puff(int whichlabel)
2176 static XYZ footvel, footpoint;
2179 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
2180 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
2184 * I think I added this in an attempt to clean up code
2186 void Person::setTargetAnimation(int animation)
2188 animTarget = animation;
2197 void Person::DoAnimations()
2199 if (!skeleton.free) {
2200 static float oldtarget;
2202 if (isIdle() && animCurrent != getIdle()) {
2203 normalsupdatedelay = 0;
2206 if (animTarget == tempanim || animCurrent == tempanim) {
2207 Animation::animations[tempanim] = tempanimation;
2209 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
2216 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
2217 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
2219 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z)) {
2222 if (!crouchkeydown && velocity.y >= -15) {
2226 if ((animCurrent == jumpupanim || animTarget == jumpdownanim) /*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
2231 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
2233 if (normaldotproduct(targfacing, velocity) >= -.3) {
2234 animTarget = flipanim;
2236 animTarget = backflipanim;
2238 crouchtogglekeydown = 1;
2247 if (Animation::animations[animTarget].attack != reversed) {
2250 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
2251 crouchtogglekeydown = 0;
2252 if (aitype == playercontrolled) {
2256 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain)) {
2260 crouchtogglekeydown = 1;
2264 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
2266 normalsupdatedelay = 0;
2271 if (animTarget == rollanim && frameTarget == 3 && onfire) {
2273 emit_sound_at(fireendsound, coords);
2274 pause_sound(stream_firesound);
2278 if (animTarget == rabbittacklinganim && frameTarget == 1) {
2279 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0) {
2282 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
2283 if (normaldotproduct(victim->facing, facing) > 0) {
2284 victim->animTarget = rabbittackledbackanim;
2286 victim->animTarget = rabbittackledfrontanim;
2288 victim->frameTarget = 2;
2291 victim->targetyaw = yaw;
2292 if (victim->aitype == gethelptype) {
2293 victim->DoDamage(victim->damagetolerance - victim->damage);
2295 //victim->DoDamage(30);
2296 if (creature == wolftype) {
2298 emit_sound_at(clawslicesound, victim->coords);
2300 victim->DoBloodBig(1 / victim->armorhead, 210);
2302 award_bonus(id, TackleBonus,
2303 victim->aitype == gethelptype ? 50 : 0);
2307 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2308 if (weapons[weaponids[0]].getType() == knife) {
2309 if (weaponactive == -1) {
2311 } else if (weaponactive == 0) {
2315 if (weaponactive == -1) {
2316 emit_sound_at(knifesheathesound, coords);
2318 if (weaponactive != -1) {
2319 emit_sound_at(knifedrawsound, coords, 128);
2322 drawtogglekeydown = 1;
2325 if (!Tutorial::active || id == 0) {
2326 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2327 int whichsound = -1;
2329 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2330 if (targetFrame().label == 1) {
2331 whichsound = footstepsound;
2333 whichsound = footstepsound2;
2335 if (targetFrame().label == 1) {
2336 FootLand(leftfoot, 1);
2338 if (targetFrame().label == 2) {
2339 FootLand(rightfoot, 1);
2341 if (targetFrame().label == 3 && isRun()) {
2342 FootLand(rightfoot, 1);
2343 FootLand(leftfoot, 1);
2346 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2347 if (targetFrame().label == 1) {
2348 whichsound = footstepsound3;
2350 whichsound = footstepsound4;
2355 if (targetFrame().label == 1) {
2356 whichsound = footstepsound3;
2358 whichsound = footstepsound4;
2361 if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2362 if (Animation::animations[animTarget].attack != neutral) {
2363 unsigned r = abs(Random() % 3);
2365 whichsound = lowwhooshsound;
2368 whichsound = midwhooshsound;
2371 whichsound = highwhooshsound;
2374 if (Animation::animations[animTarget].attack == neutral) {
2375 whichsound = movewhooshsound;
2377 } else if (targetFrame().label == 4) {
2378 whichsound = knifeswishsound;
2380 if (targetFrame().label == 8 && !Tutorial::active) {
2381 whichsound = landsound2;
2384 if (whichsound != -1) {
2385 emit_sound_at(whichsound, coords, 256.);
2388 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2389 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2390 addEnvSound(coords, 15);
2392 addEnvSound(coords, 6);
2397 if (targetFrame().label == 3) {
2399 emit_sound_at(whichsound, coords, 128.);
2406 if (!Tutorial::active || id == 0) {
2407 if (speechdelay <= 0) {
2408 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
2409 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2410 int whichsound = -1;
2411 if (targetFrame().label == 4 && aitype != playercontrolled) {
2412 if (Animation::animations[animTarget].attack != neutral) {
2413 unsigned r = abs(Random() % 4);
2414 whichsound = PersonType::types[creature].soundsAttack[r];
2419 if (whichsound != -1) {
2420 emit_sound_at(whichsound, coords);
2427 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2428 FootLand(leftfoot, 1);
2429 FootLand(rightfoot, 1);
2433 currentoffset = targetoffset;
2434 frameTarget = frameCurrent;
2435 animCurrent = animTarget;
2438 if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2439 for (unsigned i = 0; i < weapons.size(); i++) {
2440 if (weapons[i].owner == -1) {
2441 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2442 if (distsq(&coords, &weapons[i].position) >= 1) {
2443 if (weapons[i].getType() != staff) {
2444 emit_sound_at(knifedrawsound, coords, 128.);
2454 if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2455 for (unsigned i = 0; i < weapons.size(); i++) {
2456 bool willwork = true;
2457 if (weapons[i].owner != -1) {
2458 if (Person::players[weapons[i].owner]->weaponstuck != -1) {
2459 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i)) {
2460 if (Person::players[weapons[i].owner]->num_weapons > 1) {
2466 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free)) {
2467 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2468 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2469 bool fleshstuck = false;
2470 if (weapons[i].owner != -1) {
2471 if (victim->weaponstuck != -1) {
2472 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2478 emit_sound_at(fleshstabremovesound, coords, 128.);
2480 if (weapons[i].getType() != staff) {
2481 emit_sound_at(knifedrawsound, coords, 128.);
2484 if (weapons[i].owner != -1) {
2485 victim = Person::players[weapons[i].owner];
2486 if (victim->num_weapons == 1) {
2487 victim->num_weapons = 0;
2489 victim->num_weapons = 1;
2492 //victim->weaponactive=-1;
2493 victim->skeleton.longdead = 0;
2494 victim->skeleton.free = 1;
2495 victim->skeleton.broken = 0;
2497 for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) {
2498 victim->skeleton.joints[j].velchange = 0;
2499 victim->skeleton.joints[j].locked = 0;
2505 Normalise(&relative);
2506 XYZ footvel, footpoint;
2508 footpoint = weapons[i].position;
2509 if (victim->weaponstuck != -1) {
2510 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2512 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2514 weapons[i].bloody = 2;
2515 weapons[i].blooddrip = 5;
2516 victim->weaponstuck = -1;
2519 if (victim->num_weapons > 0) {
2520 if (victim->weaponstuck != 0 && victim->weaponstuck != -1) {
2521 victim->weaponstuck = 0;
2523 if (victim->weaponids[0] == int(i)) {
2524 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2528 victim->jointVel(abdomen) += relative * 6;
2529 victim->jointVel(neck) += relative * 6;
2530 victim->jointVel(rightshoulder) += relative * 6;
2531 victim->jointVel(leftshoulder) += relative * 6;
2540 if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2541 if (weaponactive == -1) {
2543 } else if (weaponactive == 0) {
2545 if (num_weapons == 2) {
2547 buffer = weaponids[0];
2548 weaponids[0] = weaponids[1];
2549 weaponids[1] = buffer;
2552 if (weaponactive == -1) {
2553 emit_sound_at(knifesheathesound, coords, 128.);
2555 if (weaponactive != -1) {
2556 emit_sound_at(knifedrawsound, coords, 128.);
2560 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2561 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2562 Normalise(&rotatetarget);
2563 targetyaw = -asin(0 - rotatetarget.x);
2564 targetyaw *= 360 / 6.28;
2565 if (rotatetarget.z < 0) {
2566 targetyaw = 180 - targetyaw;
2569 if (animTarget == walljumprightkickanim) {
2572 if (animTarget == walljumpleftkickanim) {
2579 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0)) {
2583 if (distsq(&victim->coords, &/*Person::players[i]->*/ coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1) {
2591 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2592 animTarget = rabbittackleanim;
2594 emit_sound_at(jumpsound, coords);
2602 targetloc = velocity;
2603 Normalise(&targetloc);
2604 targetloc += coords;
2605 for (unsigned i = 0; i < Person::players.size(); i++) {
2607 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2608 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2613 if (closestid != -1) {
2614 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2616 victim = Person::players[closestid];
2617 coords = victim->coords;
2618 animCurrent = rabbittacklinganim;
2619 animTarget = rabbittacklinganim;
2623 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2624 rotatetarget = coords - victim->coords;
2625 Normalise(&rotatetarget);
2626 targetyaw = -asin(0 - rotatetarget.x);
2627 targetyaw *= 360 / 6.28;
2628 if (rotatetarget.z < 0) {
2629 targetyaw = 180 - targetyaw;
2632 if (animTarget != rabbitrunninganim) {
2633 emit_sound_at(jumpsound, coords, 128.);
2640 float damagemult = 1 * power;
2641 if (creature == wolftype) {
2642 damagemult = 2.5 * power;
2645 damagemult /= victim->damagetolerance / 200;
2647 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)) {
2648 if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2649 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2654 if (Random() % 2 || creature == wolftype) {
2657 if (creature == wolftype) {
2661 if (!Tutorial::active) {
2662 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2664 if (creature == wolftype) {
2665 emit_sound_at(clawslicesound, victim->coords, 128.);
2667 victim->DoBloodBig(2 / victim->armorhead, 175);
2671 relative = victim->coords - coords;
2673 Normalise(&relative);
2674 relative = DoRotation(relative, 0, -90, 0);
2675 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2676 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2678 victim->jointVel(head) += relative * damagemult * 200;
2680 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2686 if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2687 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2692 if (Random() % 2 || creature == wolftype) {
2694 if (creature == wolftype) {
2698 emit_sound_at(whooshhitsound, victim->coords);
2699 if (creature == wolftype) {
2700 emit_sound_at(clawslicesound, victim->coords, 128.);
2702 victim->DoBloodBig(2, 175);
2706 relative = victim->coords - coords;
2708 Normalise(&relative);
2710 Normalise(&relative);
2711 relative = DoRotation(relative, 0, 90, 0);
2712 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2713 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2715 victim->jointVel(head) += relative * damagemult * 100;
2717 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2721 if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2722 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2729 if (!Tutorial::active) {
2730 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2732 if (creature == wolftype) {
2733 emit_sound_at(clawslicesound, victim->coords, 128.);
2735 victim->DoBloodBig(2 / victim->armorhead, 175);
2741 Normalise(&relative);
2742 relative = DoRotation(relative, 0, -90, 0);
2743 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2744 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2746 victim->jointVel(head) += relative * damagemult * 200;
2748 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2750 if (victim->damage > victim->damagetolerance) {
2751 award_bonus(id, style);
2758 if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2759 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2766 if (!Tutorial::active) {
2767 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2769 if (creature == wolftype) {
2770 emit_sound_at(clawslicesound, victim->coords, 128.);
2772 victim->DoBloodBig(2 / victim->armorhead, 175);
2778 Normalise(&relative);
2779 relative = DoRotation(relative, 0, 90, 0);
2780 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2781 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2783 victim->jointVel(head) += relative * damagemult * 200;
2785 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2787 if (victim->damage > victim->damagetolerance) {
2788 award_bonus(id, style);
2795 if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2796 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2805 emit_sound_at(whooshhitsound, victim->coords);
2808 relative = victim->coords - coords;
2810 Normalise(&relative);
2811 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2812 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2814 victim->jointVel(head) += relative * damagemult * 100;
2816 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2820 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
2821 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2826 emit_sound_at(whooshhitsound, victim->coords, 128.);
2828 victim->skeleton.longdead = 0;
2829 victim->skeleton.free = 1;
2830 victim->skeleton.broken = 0;
2831 victim->skeleton.spinny = 1;
2833 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2834 victim->skeleton.joints[i].velchange = 0;
2835 victim->skeleton.joints[i].delay = 0;
2836 victim->skeleton.joints[i].locked = 0;
2837 //victim->skeleton.joints[i].velocity=0;
2843 Normalise(&relative);
2844 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2845 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2846 victim->skeleton.joints[i].position.y += relative.y * .3;
2847 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2848 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2850 victim->Puff(abdomen);
2851 victim->jointVel(abdomen).y = relative.y * 400;
2855 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2856 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2861 if (!Tutorial::active) {
2862 emit_sound_at(heavyimpactsound, coords, 128.);
2865 relative = victim->coords - coords;
2867 Normalise(&relative);
2868 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2869 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2871 victim->Puff(abdomen);
2872 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2876 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2877 victim->jointVel(abdomen) += relative * damagemult * 300;
2881 if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
2882 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2887 if (!Tutorial::active) {
2888 emit_sound_at(thudsound, coords);
2891 victim->skeleton.longdead = 0;
2892 victim->skeleton.free = 1;
2893 victim->skeleton.broken = 0;
2894 victim->skeleton.spinny = 1;
2896 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2897 victim->skeleton.joints[i].velchange = 0;
2898 //victim->skeleton.joints[i].delay=0;
2899 victim->skeleton.joints[i].locked = 0;
2902 relative = victim->coords - coords;
2903 Normalise(&relative);
2905 Normalise(&relative);
2906 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2907 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2909 if (!victim->dead) {
2913 victim->Puff(abdomen);
2914 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2915 victim->jointVel(abdomen) += relative * damagemult * 200;
2917 if (!victim->dead) {
2923 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2926 if (!victim->skeleton.free) {
2932 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2933 emit_sound_at(knifesheathesound, coords, 128.);
2936 if (victim && hasvictim) {
2937 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2939 XYZ where, startpoint, endpoint, movepoint, colpoint;
2940 float rotationpoint;
2942 if (weapons[weaponids[weaponactive]].getType() == knife) {
2943 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2944 where -= victim->coords;
2945 if (!victim->skeleton.free) {
2946 where = DoRotation(where, 0, -victim->yaw, 0);
2950 startpoint.y += 100;
2954 if (weapons[weaponids[weaponactive]].getType() == sword) {
2955 where = weapons[weaponids[weaponactive]].position;
2956 where -= victim->coords;
2957 if (!victim->skeleton.free) {
2958 where = DoRotation(where, 0, -victim->yaw, 0);
2961 where = weapons[weaponids[weaponactive]].tippoint;
2962 where -= victim->coords;
2963 if (!victim->skeleton.free) {
2964 where = DoRotation(where, 0, -victim->yaw, 0);
2968 if (weapons[weaponids[weaponactive]].getType() == staff) {
2969 where = weapons[weaponids[weaponactive]].position;
2970 where -= victim->coords;
2971 if (!victim->skeleton.free) {
2972 where = DoRotation(where, 0, -victim->yaw, 0);
2975 where = weapons[weaponids[weaponactive]].tippoint;
2976 where -= victim->coords;
2977 if (!victim->skeleton.free) {
2978 where = DoRotation(where, 0, -victim->yaw, 0);
2984 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2986 if (whichtri != -1) {
2987 if (victim->dead != 2) {
2988 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2989 if (!victim->dead) {
2990 award_bonus(id, FinishedBonus);
2994 weapons[weaponids[weaponactive]].bloody = 2;
2997 victim->skeleton.longdead = 0;
2998 victim->skeleton.free = 1;
2999 victim->skeleton.broken = 0;
3001 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3002 victim->skeleton.joints[i].velchange = 0;
3003 victim->skeleton.joints[i].locked = 0;
3004 //victim->skeleton.joints[i].velocity=0;
3006 emit_sound_at(fleshstabsound, coords, 128);
3008 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
3009 weapons[weaponids[weaponactive]].blooddrip += 5;
3010 weapons[weaponids[weaponactive]].blooddripdelay = 0;
3012 if (whichtri == -1) {
3014 emit_sound_at(knifesheathesound, coords, 128.);
3020 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3022 emit_sound_at(knifedrawsound, coords, 128);
3025 if (victim && hasvictim) {
3026 XYZ footvel, footpoint;
3028 emit_sound_at(fleshstabremovesound, coords, 128.);
3031 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
3033 if (weapons[weaponids[weaponactive]].getType() == sword) {
3034 XYZ where, startpoint, endpoint, movepoint;
3035 float rotationpoint;
3038 where = weapons[weaponids[weaponactive]].position;
3039 where -= victim->coords;
3040 if (!victim->skeleton.free) {
3041 where = DoRotation(where, 0, -victim->yaw, 0);
3044 where = weapons[weaponids[weaponactive]].tippoint;
3045 where -= victim->coords;
3046 if (!victim->skeleton.free) {
3047 where = DoRotation(where, 0, -victim->yaw, 0);
3053 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
3054 footpoint += victim->coords;
3056 if (whichtri == -1) {
3057 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
3060 if (weapons[weaponids[weaponactive]].getType() == staff) {
3061 XYZ where, startpoint, endpoint, movepoint;
3062 float rotationpoint;
3065 where = weapons[weaponids[weaponactive]].position;
3066 where -= victim->coords;
3067 if (!victim->skeleton.free) {
3068 where = DoRotation(where, 0, -victim->yaw, 0);
3071 where = weapons[weaponids[weaponactive]].tippoint;
3072 where -= victim->coords;
3073 if (!victim->skeleton.free) {
3074 where = DoRotation(where, 0, -victim->yaw, 0);
3080 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
3081 footpoint += victim->coords;
3083 if (whichtri == -1) {
3084 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
3087 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
3089 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
3090 victim->skeleton.longdead = 0;
3091 victim->skeleton.free = 1;
3092 victim->skeleton.broken = 0;
3094 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3095 victim->skeleton.joints[i].velchange = 0;
3096 victim->skeleton.joints[i].locked = 0;
3097 //victim->skeleton.joints[i].velocity=0;
3103 Normalise(&relative);
3104 //victim->Puff(abdomen);
3106 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
3109 if (victim->bloodloss < victim->damagetolerance) {
3110 victim->bloodloss += 1000;
3114 victim->jointVel(abdomen) += relative * damagemult * 20;
3118 if (!hasvictim && onterrain) {
3119 weapons[weaponids[weaponactive]].bloody = 0;
3120 weapons[weaponids[weaponactive]].blooddrip = 0;
3124 if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3125 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
3134 if (!Tutorial::active) {
3135 emit_sound_at(heavyimpactsound, victim->coords, 128);
3140 relative = victim->coords - coords;
3142 Normalise(&relative);
3143 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3144 victim->skeleton.joints[i].velocity = relative * 30;
3146 victim->jointVel(head) += relative * damagemult * 150;
3148 victim->frameTarget = 0;
3149 victim->animTarget = staggerbackhardanim;
3150 victim->targetyaw = targetyaw + 180;
3152 victim->stunned = 1;
3155 victim->Puff(abdomen);
3156 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
3162 if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3163 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
3168 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
3169 if (!Tutorial::active) {
3170 emit_sound_at(thudsound, victim->coords);
3172 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
3173 if (!Tutorial::active) {
3174 emit_sound_at(whooshhitsound, victim->coords);
3177 if (!Tutorial::active) {
3178 emit_sound_at(heavyimpactsound, victim->coords);
3182 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight) {
3186 relative = victim->coords - coords;
3188 Normalise(&relative);
3190 Normalise(&relative);
3191 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3192 victim->skeleton.joints[i].velocity = relative * 5;
3194 victim->jointVel(abdomen) += relative * damagemult * 400;
3196 victim->frameTarget = 0;
3197 victim->animTarget = staggerbackhardanim;
3198 victim->targetyaw = targetyaw + 180;
3200 victim->stunned = 1;
3202 victim->Puff(abdomen);
3203 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
3209 if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3210 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3211 if (victim->id == 0) {
3214 emit_sound_at(landsound2, victim->coords);
3220 if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3221 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3222 if (victim->id == 0) {
3226 if (weaponactive != -1) {
3227 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3228 if (weapons[victim->weaponids[0]].getType() == staff) {
3229 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3231 if (weapons[weaponids[0]].getType() == staff) {
3232 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3235 emit_sound_at(swordstaffsound, victim->coords);
3237 emit_sound_at(metalhitsound, victim->coords);
3245 if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3246 if (weaponactive != -1) {
3249 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);
3251 weapons[weaponids[0]].thrown(aim * 50);
3254 weaponids[0] = weaponids[num_weapons];
3260 if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3262 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 && /*Animation::animations[victim->animTarget].height!=lowheight&&*/ victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
3264 if (!Tutorial::active) {
3265 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
3268 award_bonus(id, Slicebonus);
3269 if (!Tutorial::active) {
3270 emit_sound_at(knifeslicesound, victim->coords);
3272 //victim->jointVel(abdomen)+=relative*damagemult*200;
3273 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
3274 if (victim->id != 0 || difficulty == 2) {
3275 victim->frameTarget = 0;
3276 victim->animTarget = staggerbackhardanim;
3277 victim->targetyaw = targetyaw + 180;
3281 victim->lowreversaldelay = 0;
3282 victim->highreversaldelay = 0;
3283 if (aitype != playercontrolled) {
3284 weaponmissdelay = .6;
3287 if (!Tutorial::active) {
3288 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3289 weapons[weaponids[weaponactive]].bloody = 1;
3291 weapons[weaponids[weaponactive]].blooddrip += 3;
3294 XYZ footvel, footpoint;
3296 if (skeleton.free) {
3297 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3299 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3301 if (Tutorial::active) {
3302 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
3305 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
3307 footvel = DoRotation(facing, 0, 90, 0) * .8;
3308 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3309 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3310 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3311 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3313 victim->DoDamage(damagemult * 0);
3317 if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3318 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
3319 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
3320 award_bonus(id, Slashbonus);
3322 if (!Tutorial::active) {
3323 if (normaldotproduct(victim->facing, victim->coords - coords) < 0) {
3324 victim->DoBloodBig(2 / victim->armorhigh, 190);
3326 victim->DoBloodBig(2 / victim->armorhigh, 185);
3328 victim->deathbleeding = 1;
3329 emit_sound_at(swordslicesound, victim->coords);
3330 victim->frameTarget = 0;
3331 victim->animTarget = staggerbackhardanim;
3332 victim->targetyaw = targetyaw + 180;
3334 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3335 weapons[weaponids[weaponactive]].bloody = 1;
3337 weapons[weaponids[weaponactive]].blooddrip += 3;
3339 float bloodlossamount;
3340 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
3341 victim->bloodloss += bloodlossamount / victim->armorhigh;
3342 victim->DoDamage(damagemult * 0);
3344 XYZ footvel, footpoint;
3346 if (skeleton.free) {
3347 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3349 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3352 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3354 footvel = DoRotation(facing, 0, 90, 0) * .8;
3356 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3357 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3358 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3359 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3362 if (victim->weaponactive != -1) {
3363 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3364 if (weapons[victim->weaponids[0]].getType() == staff) {
3365 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3367 if (weapons[weaponids[0]].getType() == staff) {
3368 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3371 emit_sound_at(swordstaffsound, victim->coords);
3373 emit_sound_at(metalhitsound, victim->coords);
3378 victim->Puff(righthand);
3380 victim->frameTarget = 0;
3381 victim->animTarget = staggerbackhighanim;
3382 victim->targetyaw = targetyaw + 180;
3384 aim = DoRotation(facing, 0, 90, 0) * 21;
3386 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3387 victim->num_weapons--;
3388 if (victim->num_weapons) {
3389 victim->weaponids[0] = victim->weaponids[num_weapons];
3390 if (victim->weaponstuck == victim->num_weapons) {
3391 victim->weaponstuck = 0;
3394 victim->weaponactive = -1;
3395 for (unsigned i = 0; i < Person::players.size(); i++) {
3396 Person::players[i]->wentforweapon = 0;
3402 if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3403 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3404 if (!Tutorial::active) {
3405 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3410 if (Random() % 2 || creature == wolftype) {
3413 emit_sound_at(staffheadsound, victim->coords);
3417 relative = victim->coords - coords;
3419 Normalise(&relative);
3420 relative = DoRotation(relative, 0, 90, 0);
3422 Normalise(&relative);
3423 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3424 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3426 victim->jointVel(head) += relative * damagemult * 230;
3427 victim->jointVel(neck) += relative * damagemult * 230;
3429 if (!Tutorial::active) {
3430 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3432 award_bonus(id, solidhit, 30);
3437 if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3438 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3439 if (!Tutorial::active) {
3440 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3445 if (Random() % 2 || creature == wolftype) {
3448 emit_sound_at(staffheadsound, victim->coords);
3452 relative = victim->coords - coords;
3454 Normalise(&relative);
3455 relative = DoRotation(relative, 0, -90, 0);
3456 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3457 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3459 victim->jointVel(head) += relative * damagemult * 220;
3460 victim->jointVel(neck) += relative * damagemult * 220;
3462 if (!Tutorial::active) {
3463 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3465 award_bonus(id, solidhit, 60);
3470 if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3471 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3473 if (!Tutorial::active) {
3474 if (!victim->dead) {
3475 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3480 if (Random() % 2 || creature == wolftype) {
3483 emit_sound_at(staffbodysound, victim->coords);
3485 victim->skeleton.longdead = 0;
3486 victim->skeleton.free = 1;
3487 victim->skeleton.broken = 0;
3489 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3490 victim->skeleton.joints[i].velchange = 0;
3491 victim->skeleton.joints[i].locked = 0;
3492 //victim->skeleton.joints[i].velocity=0;
3499 Normalise(&relative);
3500 if (!victim->dead) {
3501 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3502 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3504 victim->jointVel(abdomen) += relative * damagemult * 40;
3507 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3508 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3511 victim->Puff(abdomen);
3512 if (!Tutorial::active) {
3513 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3515 if (!victim->dead) {
3516 award_bonus(id, solidhit, 40);
3522 if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3523 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3529 relative = victim->coords - coords;
3531 Normalise(&relative);
3535 if (Animation::animations[victim->animTarget].height == lowheight) {
3541 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3542 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3544 victim->jointVel(head) += relative * damagemult * 200;
3545 if (!Tutorial::active) {
3546 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3549 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3550 if (victim->howactive == typesleeping) {
3551 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3553 if (creature == wolftype) {
3554 emit_sound_at(clawslicesound, victim->coords, 128.);
3556 victim->DoBloodBig(2 / victim->armorhead, 175);
3559 if (victim->damage >= victim->damagetolerance) {
3562 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3563 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3565 victim->jointVel(abdomen) += relative * damagemult * 200;
3566 victim->frameTarget = 0;
3567 victim->animTarget = staggerbackhighanim;
3568 victim->targetyaw = targetyaw + 180;
3570 if (!Tutorial::active) {
3571 emit_sound_at(landsound2, victim->coords, 128.);
3573 victim->Puff(abdomen);
3574 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3575 if (creature == wolftype) {
3576 emit_sound_at(clawslicesound, victim->coords, 128.);
3578 victim->DoBloodBig(2 / victim->armorhigh, 170);
3584 if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3585 if ((victim->animTarget != jumpupanim) &&
3586 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3587 (victim != this->shared_from_this())) {
3592 if (!Tutorial::active) {
3593 emit_sound_at(landsound2, victim->coords, 128.);
3596 relative = victim->coords - coords;
3598 Normalise(&relative);
3600 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3603 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3604 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3606 relative = DoRotation(relative, 0, -90, 0);
3608 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3609 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) {
3610 victim->skeleton.joints[i].velocity = relative * 80;
3613 victim->Puff(rightankle);
3614 victim->Puff(leftankle);
3615 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3617 if (victim->damage >= victim->damagetolerance) {
3620 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3621 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3623 relative = DoRotation(relative, 0, -90, 0);
3624 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3625 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) {
3626 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3629 victim->jointVel(abdomen) += relative * damagemult * 200;
3630 victim->frameTarget = 0;
3631 victim->animTarget = staggerbackhighanim;
3632 victim->targetyaw = targetyaw + 180;
3634 if (!Tutorial::active) {
3635 emit_sound_at(landsound2, victim->coords, 128.);
3637 victim->Puff(abdomen);
3638 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3645 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3646 if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3655 if (!Tutorial::active) {
3656 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3658 if (creature == wolftype) {
3659 emit_sound_at(clawslicesound, victim->coords, 128);
3661 victim->DoBloodBig(2 / victim->armorhigh, 170);
3665 relative = victim->coords - oldcoords;
3667 Normalise(&relative);
3668 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3669 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3671 victim->jointVel(abdomen) += relative * damagemult * 200;
3672 victim->Puff(abdomen);
3673 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3675 award_bonus(id, Reversal);
3678 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3679 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3680 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3681 takeWeapon(victim->weaponids[victim->weaponactive]);
3682 victim->num_weapons--;
3683 if (victim->num_weapons > 0) {
3684 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3686 victim->weaponactive = -1;
3691 if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3700 emit_sound_at(whooshhitsound, victim->coords, 128.);
3703 relative = victim->coords - oldcoords;
3705 Normalise(&relative);
3706 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3707 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3709 victim->jointVel(abdomen) += relative * damagemult * 200;
3711 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3714 if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3724 award_bonus(id, staffreversebonus);
3726 if (!Tutorial::active) {
3727 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3730 award_bonus(id, staffreversebonus); // Huh, again?
3733 relative = victim->coords - oldcoords;
3735 Normalise(&relative);
3736 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3737 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3739 victim->jointVel(abdomen) += relative * damagemult * 200;
3741 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3744 if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3750 Normalise(&relative);
3752 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3753 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3755 victim->jointVel(lefthand) *= .1;
3756 victim->jointVel(leftwrist) *= .2;
3757 victim->jointVel(leftelbow) *= .5;
3758 victim->jointVel(leftshoulder) *= .7;
3759 victim->jointVel(righthand) *= .1;
3760 victim->jointVel(rightwrist) *= .2;
3761 victim->jointVel(rightelbow) *= .5;
3762 victim->jointVel(rightshoulder) *= .7;
3764 victim->Puff(abdomen);
3765 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3767 award_bonus(id, Reversal);
3771 if (weaponactive != -1 || creature == wolftype) {
3774 if (creature == rabbittype && weaponactive != -1) {
3775 if (weapons[weaponids[0]].getType() == staff) {
3780 if (weaponactive != -1) {
3781 victim->DoBloodBig(2 / victim->armorhigh, 225);
3782 emit_sound_at(knifeslicesound, victim->coords);
3783 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3784 weapons[weaponids[weaponactive]].bloody = 1;
3786 weapons[weaponids[weaponactive]].blooddrip += 3;
3788 if (weaponactive == -1 && creature == wolftype) {
3789 emit_sound_at(clawslicesound, victim->coords, 128.);
3791 victim->DoBloodBig(2 / victim->armorhigh, 175);
3796 if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3802 Normalise(&relative);
3804 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3805 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3807 victim->jointVel(lefthand) *= .1 - 1;
3808 victim->jointVel(leftwrist) *= .2 - 1;
3809 victim->jointVel(leftelbow) *= .5 - 1;
3810 victim->jointVel(leftshoulder) *= .7 - 1;
3811 victim->jointVel(righthand) *= .1 - 1;
3812 victim->jointVel(rightwrist) *= .2 - 1;
3813 victim->jointVel(rightelbow) *= .5 - 1;
3814 victim->jointVel(rightshoulder) *= .7 - 1;
3816 award_bonus(id, swordreversebonus);
3819 if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3828 if (!Tutorial::active) {
3829 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3833 relative = victim->coords - oldcoords;
3835 Normalise(&relative);
3836 relative = DoRotation(relative, 0, -90, 0);
3837 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3838 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3840 victim->jointVel(abdomen) += relative * damagemult * 200;
3841 victim->Puff(abdomen);
3842 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3844 award_bonus(id, Reversal);
3847 if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3850 victim->skeleton.spinny = 0;
3852 relative = facing * -1;
3854 Normalise(&relative);
3855 if (victim->id == 0) {
3858 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3859 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3861 victim->damage = victim->damagetolerance;
3862 victim->permanentdamage = victim->damagetolerance - 1;
3865 if (weaponactive != -1 || creature == wolftype) {
3868 if (creature == rabbittype && weaponactive != -1) {
3869 if (weapons[weaponids[0]].getType() == staff) {
3874 if (weaponactive != -1) {
3875 victim->DoBloodBig(200, 225);
3876 emit_sound_at(knifeslicesound, victim->coords);
3878 weapons[weaponids[weaponactive]].bloody = 2;
3880 weapons[weaponids[weaponactive]].blooddrip += 5;
3883 if (creature == wolftype && weaponactive == -1) {
3884 emit_sound_at(clawslicesound, victim->coords, 128.);
3886 victim->DoBloodBig(2, 175);
3889 award_bonus(id, spinecrusher);
3892 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3893 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3895 if (animTarget == knifefollowanim) {
3896 victim->DoBloodBig(200, 210);
3898 if (animTarget == knifesneakattackanim) {
3899 XYZ footvel, footpoint;
3901 footpoint = weapons[weaponids[0]].tippoint;
3903 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3905 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3906 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3907 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3908 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3909 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3910 victim->DoBloodBig(200, 195);
3911 award_bonus(id, tracheotomy);
3913 if (animTarget == knifefollowanim) {
3914 award_bonus(id, Stabbonus);
3915 XYZ footvel, footpoint;
3917 footpoint = weapons[weaponids[0]].tippoint;
3919 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3921 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3922 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3923 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3924 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3925 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3927 victim->bloodloss += 10000;
3928 victim->velocity = 0;
3929 emit_sound_at(fleshstabsound, victim->coords);
3931 weapons[weaponids[weaponactive]].bloody = 2;
3933 weapons[weaponids[weaponactive]].blooddrip += 5;
3937 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3939 victim->velocity = 0;
3940 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3941 victim->skeleton.joints[i].velocity = 0;
3943 if (animTarget == knifefollowanim) {
3945 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3946 victim->skeleton.joints[i].velocity = 0;
3949 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3950 emit_sound_at(fleshstabremovesound, victim->coords);
3952 weapons[weaponids[weaponactive]].bloody = 2;
3954 weapons[weaponids[weaponactive]].blooddrip += 5;
3956 XYZ footvel, footpoint;
3958 footpoint = weapons[weaponids[0]].tippoint;
3960 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3962 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3963 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3964 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3965 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3966 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3970 if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3971 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3972 award_bonus(id, backstab);
3976 XYZ footvel, footpoint;
3978 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3980 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3982 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3983 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3984 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3985 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3986 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3987 victim->DoBloodBig(200, 180);
3988 victim->DoBloodBig(200, 215);
3989 victim->bloodloss += 10000;
3990 victim->velocity = 0;
3991 emit_sound_at(fleshstabsound, victim->coords);
3993 weapons[weaponids[weaponactive]].bloody = 2;
3995 weapons[weaponids[weaponactive]].blooddrip += 5;
3999 if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
4001 victim->velocity = 0;
4002 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
4003 victim->skeleton.joints[i].velocity = 0;
4005 if (weaponactive != -1) {
4006 emit_sound_at(fleshstabremovesound, victim->coords);
4008 weapons[weaponids[weaponactive]].bloody = 2;
4010 weapons[weaponids[weaponactive]].blooddrip += 5;
4012 XYZ footvel, footpoint;
4014 footpoint = weapons[weaponids[0]].tippoint;
4016 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
4018 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
4019 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
4020 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
4021 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
4022 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
4026 if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
4035 if (weaponactive == -1) {
4036 if (!Tutorial::active) {
4037 emit_sound_at(heavyimpactsound, victim->coords, 128.);
4042 if (weaponactive != -1 || creature == wolftype) {
4045 if (creature == rabbittype && weaponactive != -1) {
4046 if (weapons[weaponids[0]].getType() == staff) {
4051 if (weaponactive != -1) {
4052 victim->DoBloodBig(2 / victim->armorhead, 225);
4053 emit_sound_at(knifeslicesound, victim->coords);
4054 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
4055 weapons[weaponids[weaponactive]].bloody = 1;
4057 weapons[weaponids[weaponactive]].blooddrip += 3;
4059 if (weaponactive == -1 && creature == wolftype) {
4060 emit_sound_at(clawslicesound, victim->coords, 128.);
4062 victim->DoBloodBig(2 / victim->armorhead, 175);
4066 award_bonus(id, Reversal);
4071 relative = facing * -1;
4073 Normalise(&relative);
4074 relative = DoRotation(relative, 0, 90, 0);
4076 Normalise(&relative);
4077 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
4078 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
4080 victim->jointVel(head) += relative * damagemult * 200;
4081 if (victim->damage < victim->damagetolerance - 100) {
4082 victim->velocity = relative * 200;
4084 victim->DoDamage(damagemult * 100 / victim->protectionhead);
4085 victim->velocity = 0;
4088 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))) {
4092 relative = facing * -1;
4094 Normalise(&relative);
4095 relative = DoRotation(relative, 0, 90, 0);
4097 Normalise(&relative);
4098 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
4099 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
4101 victim->jointVel(head) += relative * damagemult * 200;
4104 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim)) {
4105 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
4106 award_bonus(id, reverseko);
4112 if (frameTarget > int(Animation::animations[animCurrent].frames.size()) - 1) {
4115 animTarget = getIdle();
4116 FootLand(leftfoot, 1);
4117 FootLand(rightfoot, 1);
4119 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
4120 animTarget = rollanim;
4122 emit_sound_at(movewhooshsound, coords, 128.);
4124 if (animCurrent == staggerbackhighanim) {
4125 animTarget = getIdle();
4127 if (animCurrent == staggerbackhardanim) {
4128 animTarget = getIdle();
4130 if (animCurrent == removeknifeanim) {
4131 animTarget = getIdle();
4133 if (animCurrent == crouchremoveknifeanim) {
4134 animTarget = getCrouch();
4136 if (animCurrent == backhandspringanim) {
4137 animTarget = getIdle();
4139 if (animCurrent == dodgebackanim) {
4140 animTarget = getIdle();
4142 if (animCurrent == drawleftanim) {
4143 animTarget = getIdle();
4145 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
4146 animTarget = getIdle();
4147 if (animCurrent == crouchdrawrightanim) {
4148 animTarget = getCrouch();
4150 if (weaponactive == -1) {
4152 } else if (weaponactive == 0) {
4154 if (num_weapons == 2) {
4156 buffer = weaponids[0];
4157 weaponids[0] = weaponids[1];
4158 weaponids[1] = buffer;
4162 if (weaponactive == -1) {
4163 emit_sound_at(knifesheathesound, coords, 128.);
4165 if (weaponactive != -1) {
4166 emit_sound_at(knifedrawsound, coords, 128.);
4169 if (animCurrent == rollanim) {
4170 animTarget = getCrouch();
4171 FootLand(leftfoot, 1);
4172 FootLand(rightfoot, 1);
4175 if (animTarget == walljumprightkickanim) {
4178 if (animTarget == walljumpleftkickanim) {
4181 animTarget = jumpdownanim;
4183 if (animCurrent == climbanim) {
4184 animTarget = getCrouch();
4186 coords += facing * .1;
4187 if (!isnormal(coords.x)) {
4198 if (animTarget == rabbitkickreversalanim) {
4199 animTarget = getCrouch();
4202 if (animTarget == jumpreversalanim) {
4203 animTarget = getCrouch();
4206 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
4207 if (attackkeydown && animTarget != walljumpfrontanim) {
4209 float closestdist = -1;
4211 if (Person::players.size() > 1) {
4212 for (unsigned i = 0; i < Person::players.size(); i++) {
4213 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4214 distance = distsq(&Person::players[i]->coords, &coords);
4215 if (closestdist == -1 || distance < closestdist) {
4216 closestdist = distance;
4222 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4223 victim = Person::players[closest];
4224 animTarget = walljumprightkickanim;
4226 XYZ rotatetarget = victim->coords - coords;
4227 Normalise(&rotatetarget);
4228 yaw = -asin(0 - rotatetarget.x);
4230 if (rotatetarget.z < 0) {
4233 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4234 velocity = (victim->coords - coords) * 4;
4239 if (animTarget == walljumpbackanim) {
4240 animTarget = backflipanim;
4242 velocity = facing * -8;
4245 resume_stream(whooshsound);
4248 if (animTarget == walljumprightanim) {
4249 animTarget = rightflipanim;
4253 velocity = DoRotation(facing, 0, 30, 0) * -8;
4256 if (animTarget == walljumpfrontanim) {
4257 animTarget = frontflipanim;
4261 velocity = facing * 8;
4265 resume_stream(whooshsound);
4268 if (animTarget == walljumpleftanim) {
4269 if (attackkeydown) {
4271 float closestdist = -1;
4273 if (Person::players.size() > 1) {
4274 for (unsigned i = 0; i < Person::players.size(); i++) {
4275 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4276 distance = distsq(&Person::players[i]->coords, &coords);
4277 if (closestdist == -1 || distance < closestdist) {
4278 closestdist = distance;
4284 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4285 victim = Person::players[closest];
4286 animTarget = walljumpleftkickanim;
4288 XYZ rotatetarget = victim->coords - coords;
4289 Normalise(&rotatetarget);
4290 yaw = -asin(0 - rotatetarget.x);
4292 if (rotatetarget.z < 0) {
4295 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4296 velocity = (victim->coords - coords) * 4;
4301 if (animTarget != walljumpleftkickanim) {
4302 animTarget = leftflipanim;
4306 velocity = DoRotation(facing, 0, -30, 0) * -8;
4310 resume_stream(whooshsound);
4313 if (animTarget == sneakattackanim) {
4314 animCurrent = getCrouch();
4315 animTarget = getCrouch();
4322 transspeed = 1000000;
4323 targetheadyaw += 180;
4324 coords -= facing * .7;
4326 coords.y = terrain.getHeight(coords.x, coords.z);
4331 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
4332 animTarget = getIdle();
4335 coords.y = terrain.getHeight(coords.x, coords.z);
4340 if (animCurrent == knifefollowanim) {
4341 animTarget = getIdle();
4344 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
4345 float ycoords = oldcoords.y;
4346 animTarget = getStop();
4351 transspeed = 1000000;
4352 targetheadyaw += 180;
4353 if (!isnormal(coords.x)) {
4356 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim) {
4357 oldcoords = coords + facing * .5;
4358 } else if (animCurrent == sweepreversalanim) {
4359 oldcoords = coords + facing * 1.1;
4360 } else if (animCurrent == upunchreversalanim) {
4361 oldcoords = coords + facing * 1.5;
4364 targetheadyaw += 180;
4367 } else if (animCurrent == knifeslashreversalanim) {
4368 oldcoords = coords + facing * .5;
4371 targetheadyaw += 90;
4374 } else if (animCurrent == staffspinhitreversalanim) {
4377 targetheadyaw += 180;
4382 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
4384 oldcoords.y = ycoords;
4386 currentoffset = coords - oldcoords;
4392 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4397 if (Animation::animations[animTarget].attack == reversed) {
4399 if (animTarget == sweepreversedanim) {
4402 animTarget = backhandspringanim;
4404 emit_sound_at(landsound, coords, 128);
4406 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4407 animTarget = rollanim;
4410 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4411 coords.y = oldcoords.y;
4413 if (animCurrent == knifeslashreversedanim) {
4414 animTarget = rollanim;
4419 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4420 coords.y = oldcoords.y;
4424 animTarget = jumpdownanim;
4427 animTarget = getIdle();
4429 if (wasLandhard()) {
4430 animTarget = getIdle();
4432 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4433 animTarget = getIdle();
4435 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4436 coords.y = oldcoords.y;
4437 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4438 targetoffset.y = coords.y;
4440 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4442 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4443 currentoffset.y -= (coords.y - targetoffset.y);
4444 coords.y = targetoffset.y;
4446 normalsupdatedelay = 0;
4448 if (animCurrent == upunchanim) {
4449 animTarget = getStop();
4450 normalsupdatedelay = 0;
4453 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4457 if (num_weapons > 0) {
4458 if (weapons[0].getType() == staff) {
4467 rabbitkickragdoll = 1;
4469 if (animCurrent == rabbitkickreversedanim) {
4475 skeleton.spinny = 0;
4476 SolidHitBonus(!id); // FIXME: tricky id
4480 animTarget = rollanim;
4483 pause_sound(whooshsound);
4488 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4492 skeleton.spinny = 0;
4494 if (animCurrent == jumpreversedanim) {
4500 skeleton.spinny = 0;
4501 SolidHitBonus(!id); // FIXME: tricky id
4505 animTarget = rollanim;
4506 coords += facing * 2;
4508 pause_sound(whooshsound);
4514 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) {
4515 animTarget = getupfromfrontanim;
4517 } else if (Animation::animations[animCurrent].attack == normalattack) {
4518 animTarget = getIdle();
4521 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4522 animTarget = blockhighleftstrikeanim;
4524 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4525 animTarget = getIdle();
4528 if (animCurrent == spinkickanim && victim->skeleton.free) {
4529 if (creature == rabbittype) {
4530 animTarget = fightidleanim;
4536 if (isIdle() && !wasIdle()) {
4537 normalsupdatedelay = 0;
4540 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4541 animTarget = jumpdownanim;
4544 if (!skeleton.free) {
4546 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4547 if (!isRun() || !wasRun()) {
4548 if (targetFrame().speed > currentFrame().speed) {
4549 target += multiplier * targetFrame().speed * speed * 2;
4551 if (targetFrame().speed <= currentFrame().speed) {
4552 target += multiplier * currentFrame().speed * speed * 2;
4555 if (isRun() && wasRun()) {
4557 tempspeed = velspeed;
4558 if (tempspeed < 10 * speedmult) {
4559 tempspeed = 10 * speedmult;
4561 /* FIXME - mixed of target and current here, is that intended? */
4562 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4564 } else if (transspeed) {
4565 target += multiplier * transspeed * speed * 2;
4567 if (!isRun() || !wasRun()) {
4568 if (targetFrame().speed > currentFrame().speed) {
4569 target += multiplier * targetFrame().speed * 2;
4571 if (targetFrame().speed <= currentFrame().speed) {
4572 target += multiplier * currentFrame().speed * 2;
4577 if (animCurrent != animTarget) {
4578 target = (target + oldtarget) / 2;
4582 frameCurrent = frameTarget;
4586 rot = targetrot * target;
4587 yaw += rot - oldrot;
4593 if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
4594 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4596 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4598 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4599 skeleton.joints[i].position = currentFrame().joints[i].position;
4602 skeleton.FindForwards();
4604 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4605 if (skeleton.muscles[i].visible) {
4606 skeleton.FindRotationMuscle(i, animTarget);
4609 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4610 if (skeleton.muscles[i].visible) {
4611 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4612 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4614 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4615 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4617 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4618 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4624 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4625 skeleton.joints[i].position = targetFrame().joints[i].position;
4628 skeleton.FindForwards();
4630 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4631 if (skeleton.muscles[i].visible) {
4632 skeleton.FindRotationMuscle(i, animTarget);
4635 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4636 if (skeleton.muscles[i].visible) {
4637 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4638 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4640 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4641 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4643 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4644 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4646 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) {
4647 skeleton.muscles[i].newrotate3 -= 360;
4649 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) {
4650 skeleton.muscles[i].newrotate3 += 360;
4652 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) {
4653 skeleton.muscles[i].newrotate2 -= 360;
4655 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) {
4656 skeleton.muscles[i].newrotate2 += 360;
4658 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) {
4659 skeleton.muscles[i].newrotate1 -= 360;
4661 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) {
4662 skeleton.muscles[i].newrotate1 += 360;
4668 oldanimCurrent = animCurrent;
4669 oldanimTarget = animTarget;
4670 oldframeTarget = frameTarget;
4671 oldframeCurrent = frameCurrent;
4673 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4674 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target - skeleton.joints[i].position) / multiplier;
4675 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target;
4677 offset = currentoffset * (1 - target) + targetoffset * target;
4678 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4679 if (skeleton.muscles[i].visible) {
4680 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * target;
4681 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * target;
4682 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * target;
4687 if (isLanding() && landhard) {
4691 animTarget = getLandhard();
4704 void Person::DoStuff()
4706 static XYZ terrainnormal;
4707 static XYZ flatfacing;
4708 static XYZ flatvelocity;
4709 static float flatvelspeed;
4710 static int bloodsize;
4711 static int startx, starty, endx, endy;
4712 static GLubyte color;
4713 static XYZ bloodvel;
4715 onfiredelay -= multiplier;
4716 if (onfiredelay < 0 && onfire) {
4717 if (Random() % 2 == 0) {
4723 crouchkeydowntime += multiplier;
4724 if (!crouchkeydown) {
4725 crouchkeydowntime = 0;
4727 jumpkeydowntime += multiplier;
4728 if (!jumpkeydown && skeleton.free) {
4729 jumpkeydowntime = 0;
4732 if (hostile || damage > 0 || bloodloss > 0) {
4736 if (isIdle() || isRun()) {
4740 if (num_weapons == 1 && weaponactive != -1) {
4745 blooddimamount -= multiplier * .3;
4747 speechdelay -= multiplier;
4748 texupdatedelay -= multiplier;
4749 interestdelay -= multiplier;
4750 flamedelay -= multiplier;
4751 parriedrecently -= multiplier;
4753 victim = this->shared_from_this();
4758 speed = 1.1 * speedmult;
4760 speed = 1.0 * speedmult;
4762 if (!skeleton.free) {
4763 rabbitkickragdoll = 0;
4768 if (id != 0 && (creature == rabbittype || difficulty != 2)) {
4771 if (id != 0 && creature == wolftype && difficulty == 2) {
4773 if (aitype != passivetype) {
4775 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) {
4782 if (animTarget == wolfrunninganim && !superruntoggle) {
4783 animTarget = getRun();
4787 if (weaponactive == -1 && num_weapons > 0) {
4788 if (weapons[weaponids[0]].getType() == staff) {
4794 burnt += multiplier;
4799 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4801 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4808 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
4809 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4813 while (flamedelay < 0 && onfire) {
4815 int howmany = fabs(Random() % (skeleton.joints.size()));
4816 if (skeleton.free) {
4817 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4818 flatfacing = skeleton.joints[howmany].position * scale + coords;
4820 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4821 flatvelocity = (coords - oldcoords) / multiplier / 2;
4823 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4826 while (flamedelay < 0 && !onfire && Tutorial::active && id != 0) {
4828 int howmany = fabs(Random() % (skeleton.joints.size()));
4829 if (skeleton.free) {
4830 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4831 flatfacing = skeleton.joints[howmany].position * scale + coords;
4833 flatvelocity = (coords - oldcoords) / multiplier / 2;
4834 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4836 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4840 bleeding -= multiplier * .3;
4841 if (bloodtoggle == 2) {
4842 skeleton.drawmodel.textureptr.bind();
4843 if ((bleeding <= 0) && (detail != 2)) {
4849 if (neckspurtamount > 0) {
4850 neckspurtamount -= multiplier;
4851 neckspurtdelay -= multiplier * 3;
4852 neckspurtparticledelay -= multiplier * 3;
4853 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4856 if (skeleton.free) {
4857 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4858 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4859 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4861 bloodvel.z = 5 * neckspurtamount;
4862 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4863 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4864 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4866 neckspurtparticledelay = .05;
4868 if (neckspurtdelay < 0) {
4873 if (deathbleeding > 0 && dead != 2) {
4874 if (deathbleeding < 5) {
4875 bleeddelay -= deathbleeding * multiplier / 4;
4877 bleeddelay -= 5 * multiplier / 4;
4879 if (bleeddelay < 0 && bloodtoggle) {
4884 if (skeleton.free) {
4885 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4886 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4888 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4889 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4893 bloodloss += deathbleeding * multiplier * 80;
4894 deathbleeding -= multiplier * 1.6;
4895 if (deathbleeding < 0) {
4898 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4899 if (weaponactive != -1) {
4900 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4901 weapons[weaponids[0]].velocity.x += .01;
4904 weaponids[0] = weaponids[num_weapons];
4905 if (weaponstuck == num_weapons) {
4910 for (unsigned i = 0; i < Person::players.size(); i++) {
4911 Person::players[i]->wentforweapon = 0;
4919 if (!dead && creature == wolftype) {
4920 award_bonus(0, Wolfbonus);
4923 if (animTarget == knifefollowedanim && !skeleton.free) {
4924 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4925 skeleton.joints[i].velocity = 0;
4926 skeleton.joints[i].velocity.y = -2;
4929 if (id != 0 && unconscioustime > .1) {
4937 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4938 texupdatedelay = .12;
4940 bloodsize = 5 - realtexdetail;
4944 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4945 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4946 endx = startx + bloodsize;
4947 endy = starty + bloodsize;
4957 if (endx > skeleton.skinsize - 1) {
4958 endx = skeleton.skinsize - 1;
4961 if (endy > skeleton.skinsize - 1) {
4962 endy = skeleton.skinsize - 1;
4965 if (endx < startx) {
4968 if (endy < starty) {
4972 for (int i = startx; i < endx; i++) {
4973 for (int j = starty; j < endy; j++) {
4974 if (Random() % 2 == 0) {
4975 color = Random() % 85 + 170;
4976 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2) {
4977 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4979 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4980 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4985 skeleton.drawmodel.textureptr.bind();
4989 if (skeleton.free) {
4990 bleedx += 4 * direction / realtexdetail;
4992 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4994 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4997 bleedy -= 4 / realtexdetail;
4999 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
5001 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
5006 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
5007 righthandmorphness = targetrighthandmorphness;
5008 righthandmorphstart = righthandmorphend;
5009 } else if (righthandmorphness > targetrighthandmorphness) {
5010 righthandmorphness -= multiplier * 4;
5011 } else if (righthandmorphness < targetrighthandmorphness) {
5012 righthandmorphness += multiplier * 4;
5015 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
5016 lefthandmorphness = targetlefthandmorphness;
5017 lefthandmorphstart = lefthandmorphend;
5018 } else if (lefthandmorphness > targetlefthandmorphness) {
5019 lefthandmorphness -= multiplier * 4;
5020 } else if (lefthandmorphness < targetlefthandmorphness) {
5021 lefthandmorphness += multiplier * 4;
5024 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
5025 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
5026 tailmorphness = targettailmorphness;
5027 tailmorphstart = tailmorphend;
5028 } else if (tailmorphness > targettailmorphness) {
5029 tailmorphness -= multiplier * 10;
5030 } else if (tailmorphness < targettailmorphness) {
5031 tailmorphness += multiplier * 10;
5035 if (creature == wolftype) {
5036 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
5037 tailmorphness = targettailmorphness;
5038 tailmorphstart = tailmorphend;
5039 } else if (tailmorphness > targettailmorphness) {
5040 tailmorphness -= multiplier * 2;
5041 } else if (tailmorphness < targettailmorphness) {
5042 tailmorphness += multiplier * 2;
5046 if (headmorphend == 3 || headmorphstart == 3) {
5047 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
5048 headmorphness = targetheadmorphness;
5049 headmorphstart = headmorphend;
5050 } else if (headmorphness > targetheadmorphness) {
5051 headmorphness -= multiplier * 7;
5052 } else if (headmorphness < targetheadmorphness) {
5053 headmorphness += multiplier * 7;
5055 } else if (headmorphend == 5 || headmorphstart == 5) {
5056 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
5057 headmorphness = targetheadmorphness;
5058 headmorphstart = headmorphend;
5059 } else if (headmorphness > targetheadmorphness) {
5060 headmorphness -= multiplier * 10;
5061 } else if (headmorphness < targetheadmorphness) {
5062 headmorphness += multiplier * 10;
5065 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
5066 headmorphness = targetheadmorphness;
5067 headmorphstart = headmorphend;
5068 } else if (headmorphness > targetheadmorphness) {
5069 headmorphness -= multiplier * 4;
5070 } else if (headmorphness < targetheadmorphness) {
5071 headmorphness += multiplier * 4;
5075 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
5076 chestmorphness = targetchestmorphness;
5077 chestmorphstart = chestmorphend;
5078 } else if (chestmorphness > targetchestmorphness) {
5079 chestmorphness -= multiplier;
5080 } else if (chestmorphness < targetchestmorphness) {
5081 chestmorphness += multiplier;
5084 if (dead != 2 && howactive <= typesleeping) {
5085 if (chestmorphstart == 0 && chestmorphend == 0) {
5087 targetchestmorphness = 1;
5090 if (chestmorphstart != 0 && chestmorphend != 0) {
5092 targetchestmorphness = 1;
5094 if (environment == snowyenvironment) {
5097 if (skeleton.free) {
5098 footvel = skeleton.specialforward[0] * -1;
5099 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
5101 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
5102 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
5104 if (animTarget == sleepanim) {
5105 footvel = DoRotation(footvel, 0, 90, 0);
5107 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
5111 if (!dead && howactive < typesleeping) {
5112 blinkdelay -= multiplier * 2;
5113 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
5115 targetheadmorphness = 1;
5117 blinkdelay = (float)(abs(Random() % 40)) / 5;
5119 if (headmorphstart == 3 && headmorphend == 3) {
5121 targetheadmorphness = 1;
5126 twitchdelay -= multiplier * 1.5;
5127 if (animTarget != hurtidleanim) {
5128 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
5130 targetheadmorphness = 1;
5132 twitchdelay = (float)(abs(Random() % 40)) / 5;
5134 if (headmorphstart == 5 && headmorphend == 5) {
5136 targetheadmorphness = 1;
5140 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
5141 twitchdelay3 -= multiplier * 1;
5142 if (Random() % 2 == 0) {
5143 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
5144 righthandmorphness = 0;
5145 targetrighthandmorphness = 1;
5146 righthandmorphend = 1;
5147 if (Random() % 2 == 0) {
5148 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
5151 if (righthandmorphstart == 1 && righthandmorphend == 1) {
5152 righthandmorphness = 0;
5153 targetrighthandmorphness = 1;
5154 righthandmorphend = 0;
5157 if (Random() % 2 == 0) {
5158 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
5159 lefthandmorphness = 0;
5160 targetlefthandmorphness = 1;
5161 lefthandmorphend = 1;
5162 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
5164 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
5165 lefthandmorphness = 0;
5166 targetlefthandmorphness = 1;
5167 lefthandmorphend = 0;
5173 if (creature == rabbittype) {
5174 if (howactive < typesleeping) {
5175 twitchdelay2 -= multiplier * 1.5;
5177 twitchdelay2 -= multiplier * 0.5;
5179 if (howactive <= typesleeping) {
5180 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
5182 targettailmorphness = 1;
5184 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
5186 if (tailmorphstart == 1 && tailmorphend == 1) {
5188 targettailmorphness = 1;
5191 if (tailmorphstart == 2 && tailmorphend == 2) {
5193 targettailmorphness = 1;
5200 if (creature == wolftype) {
5201 twitchdelay2 -= multiplier * 1.5;
5202 if (tailmorphend != 0) {
5203 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
5205 targettailmorphness = 1;
5210 if (tailmorphend != 5) {
5211 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
5213 targettailmorphness = 1;
5218 if (twitchdelay2 <= 0) {
5219 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
5221 targettailmorphness = 1;
5224 if (tailmorphstart == 1 && tailmorphend == 1) {
5226 targettailmorphness = 1;
5229 if (tailmorphstart == 2 && tailmorphend == 2) {
5231 targettailmorphness = 1;
5234 if (tailmorphstart == 3 && tailmorphend == 3) {
5236 targettailmorphness = 1;
5239 if (tailmorphstart == 4 && tailmorphend == 4) {
5241 targettailmorphness = 1;
5248 unconscioustime = 0;
5251 if (dead == 1 || howactive == typesleeping) {
5252 unconscioustime += multiplier;
5253 //If unconscious, close eyes and mouth
5254 if (righthandmorphend != 0) {
5255 righthandmorphness = 0;
5257 righthandmorphend = 0;
5258 targetrighthandmorphness = 1;
5260 if (lefthandmorphend != 0) {
5261 lefthandmorphness = 0;
5263 lefthandmorphend = 0;
5264 targetlefthandmorphness = 1;
5266 if (headmorphend != 3 && headmorphend != 5) {
5270 targetheadmorphness = 1;
5273 if (howactive > typesleeping) {
5276 if (bloodtoggle && !bled) {
5277 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5278 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5279 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5280 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5284 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5290 if (dead == 2 || howactive > typesleeping) {
5291 //If dead, open mouth and hands
5292 if (righthandmorphend != 0) {
5293 righthandmorphness = 0;
5295 righthandmorphend = 0;
5296 targetrighthandmorphness = 1;
5298 if (lefthandmorphend != 0) {
5299 lefthandmorphness = 0;
5301 lefthandmorphend = 0;
5302 targetlefthandmorphness = 1;
5304 if (headmorphend != 2) {
5308 targetheadmorphness = 1;
5311 if (stunned > 0 && !dead && headmorphend != 2) {
5312 if (headmorphend != 4) {
5316 targetheadmorphness = 1;
5319 if (damage > damagetolerance && !dead) {
5322 unconscioustime = 0;
5324 if (creature == wolftype) {
5325 award_bonus(0, Wolfbonus);
5330 if (weaponactive != -1) {
5331 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5332 weapons[weaponids[0]].velocity.x += .01;
5335 weaponids[0] = weaponids[num_weapons];
5336 if (weaponstuck == num_weapons) {
5341 for (unsigned i = 0; i < Person::players.size(); i++) {
5342 Person::players[i]->wentforweapon = 0;
5346 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
5355 damage -= multiplier * 13;
5356 permanentdamage -= multiplier * 4;
5357 if (isIdle() || isCrouch()) {
5358 permanentdamage -= multiplier * 4;
5364 if (permanentdamage < 0) {
5365 permanentdamage = 0;
5367 if (superpermanentdamage < 0) {
5368 superpermanentdamage = 0;
5370 if (permanentdamage < superpermanentdamage) {
5371 permanentdamage = superpermanentdamage;
5373 if (damage < permanentdamage) {
5374 damage = permanentdamage;
5376 if (dead == 1 && damage < damagetolerance) {
5380 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5381 skeleton.joints[i].velocity = 0;
5384 if (permanentdamage > damagetolerance && dead != 2) {
5387 if (weaponactive != -1) {
5388 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5389 weapons[weaponids[0]].velocity.x += .01;
5392 weaponids[0] = weaponids[num_weapons];
5393 if (weaponstuck == num_weapons) {
5398 for (unsigned i = 0; i < Person::players.size(); i++) {
5399 Person::players[i]->wentforweapon = 0;
5405 if (!dead && creature == wolftype) {
5406 award_bonus(0, Wolfbonus);
5409 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance) {
5410 award_bonus(id, touchofdeath);
5412 if (id != 0 && unconscioustime > .1) {
5420 emit_sound_at(breaksound, coords);
5423 if (skeleton.free == 1) {
5425 pause_sound(whooshsound);
5429 //If knocked over, open hands and close mouth
5430 if (righthandmorphend != 0) {
5431 righthandmorphness = 0;
5433 righthandmorphend = 0;
5434 targetrighthandmorphness = 1;
5436 if (lefthandmorphend != 0) {
5437 lefthandmorphness = 0;
5439 lefthandmorphend = 0;
5440 targetlefthandmorphness = 1;
5442 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
5443 if (headmorphend != 0) {
5447 targetheadmorphness = 1;
5451 skeleton.DoGravity(&scale);
5453 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
5454 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1)) {
5455 award_bonus(id, deepimpact);
5457 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5461 if (!skeleton.joints.empty()) {
5462 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5463 average += skeleton.joints[j].position;
5465 average /= skeleton.joints.size();
5466 coords += average * scale;
5467 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5468 skeleton.joints[j].position -= average;
5470 average /= multiplier;
5474 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5475 velocity += skeleton.joints[i].velocity * scale;
5477 velocity /= skeleton.joints.size();
5479 if (!isnormal(velocity.x) && velocity.x) {
5483 if (findLength(&average) < 10 && dead && skeleton.free) {
5484 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5485 if (skeleton.longdead > 2000) {
5486 if (skeleton.longdead > 6000) {
5488 pause_sound(whooshsound);
5494 if (dead == 2 && bloodloss < damagetolerance) {
5496 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5498 if (bloodtoggle && !bled) {
5499 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5500 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5501 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5502 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5503 float size = .2 * 1.2;
5506 Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5511 if (dead == 2 && bloodloss >= damagetolerance) {
5513 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5514 if (bleeding <= 0) {
5517 if (bloodtoggle && !bled) {
5518 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5519 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5520 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5521 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5525 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5533 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5534 bool canrecover = 1;
5535 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5536 startpoint = coords;
5539 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1) {
5542 if (velocity.y < -30) {
5545 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5546 if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) {
5547 colviewer = startpoint;
5548 coltarget = endpoint;
5549 if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1) {
5559 terrainnormal = jointPos(groin) - jointPos(abdomen);
5560 if (joint(groin).locked && joint(abdomen).locked) {
5561 terrainnormal = jointPos(groin) - jointPos(abdomen);
5562 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5564 if (joint(abdomen).locked && joint(neck).locked) {
5565 terrainnormal = jointPos(abdomen) - jointPos(neck);
5566 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5568 if (joint(groin).locked && joint(neck).locked) {
5569 terrainnormal = jointPos(groin) - jointPos(neck);
5570 middle = (jointPos(groin) + jointPos(neck)) / 2;
5572 Normalise(&terrainnormal);
5574 targetyaw = -asin(0 - terrainnormal.x);
5575 targetyaw *= 360 / 6.28;
5576 if (terrainnormal.z < 0) {
5577 targetyaw = 180 - targetyaw;
5582 animTarget = flipanim;
5583 crouchtogglekeydown = 1;
5588 animCurrent = tempanim;
5592 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5593 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5594 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5599 if (findLength(&average) < 10 && !dead && skeleton.free) {
5600 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5601 if (skeleton.longdead > (damage + 500) * 1.5) {
5603 pause_sound(whooshsound);
5610 terrainnormal = jointPos(groin) - jointPos(abdomen);
5611 if (joint(groin).locked && joint(abdomen).locked) {
5612 terrainnormal = jointPos(groin) - jointPos(abdomen);
5613 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5615 if (joint(abdomen).locked && joint(neck).locked) {
5616 terrainnormal = jointPos(abdomen) - jointPos(neck);
5617 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5619 if (joint(groin).locked && joint(neck).locked) {
5620 terrainnormal = jointPos(groin) - jointPos(neck);
5621 middle = (jointPos(groin) + jointPos(neck)) / 2;
5623 Normalise(&terrainnormal);
5625 targetyaw = -asin(0 - terrainnormal.x);
5626 targetyaw *= 360 / 6.28;
5627 if (terrainnormal.z < 0) {
5628 targetyaw = 180 - targetyaw;
5632 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5634 if (skeleton.forward.y < 0) {
5635 animTarget = getupfrombackanim;
5639 if (skeleton.forward.y > -.3) {
5640 animTarget = getupfromfrontanim;
5648 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5649 animTarget = rollanim;
5650 targetyaw = lookyaw;
5654 if (forwardkeydown) {
5663 if (forwardkeydown) {
5671 if (!leftkeydown && !rightkeydown) {
5679 if (abs(targettilt2) > 50) {
5682 animCurrent = tempanim;
5685 tilt2 = targettilt2;
5687 if (middle.y > 0 && animTarget != rollanim) {
5688 targetoffset.y = middle.y + 1;
5691 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5692 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5693 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5700 if (num_weapons > 0) {
5701 if (weapons[0].getType() == staff) {
5705 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5706 if (velocity.y > -30) {
5708 tempvelocity = velocity;
5709 Normalise(&tempvelocity);
5710 targetyaw = -asin(0 - tempvelocity.x);
5711 targetyaw *= 360 / 6.28;
5712 if (velocity.z < 0) {
5713 targetyaw = 180 - targetyaw;
5718 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5719 animTarget = rollanim;
5722 animTarget = backhandspringanim;
5728 emit_sound_at(movewhooshsound, coords, 128.);
5730 animCurrent = animTarget;
5731 frameCurrent = frameTarget - 1;
5743 if (skeleton.freefall == 0) {
5748 if (aitype != passivetype || skeleton.free == 1) {
5749 if (findLengthfast(&velocity) > .1) {
5750 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5751 if (Object::objects[i]->type == firetype) {
5752 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) {
5754 if (!Object::objects[i]->onfire) {
5755 emit_sound_at(firestartsound, Object::objects[i]->position);
5757 Object::objects[i]->onfire = 1;
5760 if (Object::objects[i]->onfire) {
5766 if (Object::objects[i]->type == bushtype) {
5767 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) {
5769 if (!Object::objects[i]->onfire) {
5770 emit_sound_at(firestartsound, Object::objects[i]->position);
5772 Object::objects[i]->onfire = 1;
5776 if (Object::objects[i]->onfire) {
5780 if (Object::objects[i]->messedwith <= 0) {
5784 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5787 addEnvSound(coords, 4 * findLength(&velocity));
5791 if (environment == grassyenvironment) {
5792 howmany = findLength(&velocity) * 4;
5794 if (environment == snowyenvironment) {
5795 howmany = findLength(&velocity) * 2;
5798 if (environment != desertenvironment) {
5799 for (int j = 0; j < howmany; j++) {
5800 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5801 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5802 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5805 pos.x += float(abs(Random() % 100) - 50) / 200;
5806 pos.y += float(abs(Random() % 100) - 50) / 200;
5807 pos.z += float(abs(Random() % 100) - 50) / 200;
5808 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);
5809 Sprite::setLastSpriteSpecial(1);
5813 howmany = findLength(&velocity) * 4;
5815 if (environment == snowyenvironment) {
5816 for (int j = 0; j < howmany; j++) {
5817 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5818 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5819 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5822 pos.x += float(abs(Random() % 100) - 50) / 200;
5823 pos.y += float(abs(Random() % 100) - 50) / 200;
5824 pos.z += float(abs(Random() % 100) - 50) / 200;
5825 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5826 Sprite::setLastSpriteSpecial(2);
5831 Object::objects[i]->rotx += velocity.x * multiplier * 6;
5832 Object::objects[i]->roty += velocity.z * multiplier * 6;
5833 Object::objects[i]->messedwith = .5;
5837 if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) {
5838 if (Object::objects[i]->pitch == 0) {
5841 tempcoord = coords - Object::objects[i]->position;
5842 tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0);
5843 tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0);
5844 tempcoord += Object::objects[i]->position;
5846 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) {
5847 if (Object::objects[i]->messedwith <= 0) {
5851 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5854 addEnvSound(coords, 4 * findLength(&velocity));
5858 if (environment == grassyenvironment) {
5859 howmany = findLength(&velocity) * 4;
5861 if (environment == snowyenvironment) {
5862 howmany = findLength(&velocity) * 2;
5865 if (environment != desertenvironment) {
5866 for (int j = 0; j < howmany; j++) {
5867 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5868 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5869 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5871 pos += velocity * .1;
5873 pos.x += float(abs(Random() % 100) - 50) / 150;
5874 pos.y += float(abs(Random() % 100) - 50) / 150;
5875 pos.z += float(abs(Random() % 100) - 50) / 150;
5876 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);
5877 Sprite::setLastSpriteSpecial(1);
5881 howmany = findLength(&velocity) * 4;
5883 if (environment == snowyenvironment) {
5884 for (int j = 0; j < howmany; j++) {
5885 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5886 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5887 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5889 pos += velocity * .1;
5891 pos.x += float(abs(Random() % 100) - 50) / 150;
5892 pos.y += float(abs(Random() % 100) - 50) / 150;
5893 pos.z += float(abs(Random() % 100) - 50) / 150;
5894 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5895 Sprite::setLastSpriteSpecial(2);
5900 Object::objects[i]->messedwith = .5;
5907 if (!skeleton.free) {
5910 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype) {
5914 if (aitype != passivetype && victim->skeleton.free && !victim->dead) {
5918 if (Tutorial::active && id != 0) {
5921 if (play && aitype != playercontrolled) {
5922 int whichsound = -1;
5923 if (speechdelay <= 0) {
5924 unsigned int i = abs(Random() % 4);
5926 whichsound = PersonType::types[creature].soundsTalk[i];
5931 if (whichsound != -1) {
5932 emit_sound_at(whichsound, coords);
5936 if (animTarget == staggerbackhighanim) {
5939 if (animTarget == staggerbackhardanim) {
5942 staggerdelay -= multiplier;
5943 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
5946 if (velocity.y < -30 && animTarget == jumpdownanim) {
5949 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5950 animTarget = getIdle();
5954 weaponmissdelay -= multiplier;
5955 highreversaldelay -= multiplier;
5956 lowreversaldelay -= multiplier;
5957 lastcollide -= multiplier;
5958 skiddelay -= multiplier;
5959 if (!isnormal(velocity.x) && velocity.x) {
5962 if (!isnormal(targettilt) && targettilt) {
5965 if (!isnormal(targettilt2) && targettilt2) {
5968 if (!isnormal(targetyaw) && targetyaw) {
5972 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5973 //open hands and close mouth
5974 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5975 righthandmorphness = 0;
5976 righthandmorphend = 0;
5977 targetrighthandmorphness = 1;
5980 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5981 lefthandmorphness = 0;
5982 lefthandmorphend = 0;
5983 targetlefthandmorphness = 1;
5986 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5989 targetheadmorphness = 1;
5993 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) {
5994 //open hands and mouth
5995 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5996 righthandmorphness = 0;
5997 righthandmorphend = 0;
5998 targetrighthandmorphness = 1;
6001 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
6002 lefthandmorphness = 0;
6003 lefthandmorphend = 0;
6004 targetlefthandmorphness = 1;
6007 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
6010 targetheadmorphness = 1;
6014 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
6015 //close hands and mouth
6016 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
6017 righthandmorphness = 0;
6018 righthandmorphend = 1;
6019 targetrighthandmorphness = 1;
6022 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
6023 lefthandmorphness = 0;
6024 lefthandmorphend = 1;
6025 targetlefthandmorphness = 1;
6028 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
6031 targetheadmorphness = 1;
6035 if (animTarget == spinkickanim ||
6036 animTarget == staffspinhitreversalanim ||
6037 animTarget == staffspinhitreversedanim ||
6038 animTarget == staffhitreversalanim ||
6039 animTarget == staffhitreversedanim ||
6040 animTarget == hurtidleanim ||
6041 animTarget == winduppunchanim ||
6042 animTarget == swordslashreversalanim ||
6043 animTarget == swordslashreversedanim ||
6044 animTarget == knifeslashreversalanim ||
6045 animTarget == knifeslashreversedanim ||
6046 animTarget == knifethrowanim ||
6047 animTarget == knifefollowanim ||
6048 animTarget == knifefollowedanim ||
6049 animTarget == killanim ||
6050 animTarget == dropkickanim ||
6051 animTarget == upunchanim ||
6052 animTarget == knifeslashstartanim ||
6053 animTarget == swordslashanim ||
6054 animTarget == staffhitanim ||
6055 animTarget == staffspinhitanim ||
6056 animTarget == staffgroundsmashanim ||
6057 animTarget == spinkickreversalanim ||
6058 animTarget == sweepreversalanim ||
6059 animTarget == lowkickanim ||
6060 animTarget == sweepreversedanim ||
6061 animTarget == rabbitkickreversalanim ||
6062 animTarget == rabbitkickreversedanim ||
6063 animTarget == jumpreversalanim ||
6064 animTarget == jumpreversedanim) {
6065 //close hands and yell
6066 if (righthandmorphend != 1 &&
6067 righthandmorphness == targetrighthandmorphness) {
6068 righthandmorphness = 0;
6069 righthandmorphend = 1;
6070 targetrighthandmorphness = 1;
6073 if (lefthandmorphend != 1 &&
6074 lefthandmorphness == targetlefthandmorphness) {
6075 lefthandmorphness = 0;
6076 lefthandmorphend = 1;
6077 targetlefthandmorphness = 1;
6080 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
6083 targetheadmorphness = 1;
6090 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
6091 (victim->aitype != searchtype) && (aitype != passivetype) &&
6092 (aitype != searchtype) && (victim->id < Person::players.size())) {
6093 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
6097 if (!dead && animTarget != hurtidleanim) {
6098 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
6099 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
6102 targetheadmorphness = 1;
6107 if (weaponactive != -1) {
6108 if (weapons[weaponids[weaponactive]].getType() != staff) {
6109 righthandmorphstart = 1;
6110 righthandmorphend = 1;
6112 if (weapons[weaponids[weaponactive]].getType() == staff) {
6113 righthandmorphstart = 2;
6114 righthandmorphend = 2;
6116 targetrighthandmorphness = 1;
6119 terrainnormal = terrain.getNormal(coords.x, coords.z);
6121 if (Animation::animations[animTarget].attack != reversal) {
6122 if (!isnormal(coords.x)) {
6131 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
6132 facing = flatfacing;
6133 ReflectVector(&facing, terrainnormal);
6137 animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
6139 targettilt2 = -facing.y * 20;
6145 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim) {
6148 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6149 flatvelocity = velocity;
6151 flatvelspeed = findLength(&flatvelocity);
6152 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
6153 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
6154 if (velocity.y < 0) {
6157 if (velocity.y < 0) {
6160 if (targettilt > 25) {
6163 if (targettilt < -25) {
6168 if (targettilt2 > 45) {
6171 if (targettilt2 < -45) {
6174 if (abs(tilt2 - targettilt2) < multiplier * 400) {
6175 tilt2 = targettilt2;
6176 } else if (tilt2 > targettilt2) {
6177 tilt2 -= multiplier * 400;
6178 } else if (tilt2 < targettilt2) {
6179 tilt2 += multiplier * 400;
6181 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
6190 if (!isnormal(targettilt) && targettilt) {
6193 if (!isnormal(targettilt2) && targettilt2) {
6198 if (animTarget == rabbittackleanim) {
6199 velocity += facing * multiplier * speed * 700 * scale;
6200 velspeed = findLength(&velocity);
6201 if (velspeed > speed * 65 * scale) {
6202 velocity /= velspeed;
6203 velspeed = speed * 65 * scale;
6204 velocity *= velspeed;
6206 velocity.y += gravity * multiplier * 20;
6207 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6208 velspeed = findLength(&velocity);
6209 velocity = flatfacing * velspeed;
6211 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
6212 if (isRun() || animTarget == rabbitkickanim) {
6213 velocity += facing * multiplier * speed * 700 * scale;
6214 velspeed = findLength(&velocity);
6215 if (velspeed > speed * 45 * scale) {
6216 velocity /= velspeed;
6217 velspeed = speed * 45 * scale;
6218 velocity *= velspeed;
6220 velocity.y += gravity * multiplier * 20;
6221 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6222 velspeed = findLength(&velocity);
6223 if (velspeed < speed * 30 * scale) {
6224 velspeed = speed * 30 * scale;
6226 velocity = flatfacing * velspeed;
6228 } else if (isRun()) {
6229 velocity += facing * multiplier * speed * 700 * scale;
6230 velspeed = findLength(&velocity);
6231 if (creature == rabbittype) {
6232 if (velspeed > speed * 55 * scale) {
6233 velocity /= velspeed;
6234 velspeed = speed * 55 * scale;
6235 velocity *= velspeed;
6238 if (creature == wolftype) {
6239 if (velspeed > speed * 75 * scale) {
6240 velocity /= velspeed;
6241 velspeed = speed * 75 * scale;
6242 velocity *= velspeed;
6245 velocity.y += gravity * multiplier * 20;
6246 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6247 velspeed = findLength(&velocity);
6248 velocity = flatfacing * velspeed;
6251 if (animTarget == rollanim && targetFrame().label != 6) {
6252 velocity += facing * multiplier * speed * 700 * scale;
6253 velspeed = findLength(&velocity);
6254 if (velspeed > speed * 45 * scale) {
6255 velocity /= velspeed;
6256 velspeed = speed * 45 * scale;
6257 velocity *= velspeed;
6259 velocity.y += gravity * multiplier * 20;
6260 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6261 velspeed = findLength(&velocity);
6262 velocity = flatfacing * velspeed;
6265 if (animTarget == sneakanim || animTarget == walkanim) {
6266 velocity += facing * multiplier * speed * 700 * scale;
6267 velspeed = findLength(&velocity);
6268 if (velspeed > speed * 12 * scale) {
6269 velocity /= velspeed;
6270 velspeed = speed * 12 * scale;
6271 velocity *= velspeed;
6273 velocity.y += gravity * multiplier * 20;
6274 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6275 velspeed = findLength(&velocity);
6276 velocity = flatfacing * velspeed;
6279 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
6280 velocity += facing * multiplier * speed * 700 * scale;
6281 velspeed = findLength(&velocity);
6282 if (velspeed > speed * 2 * scale) {
6283 velocity /= velspeed;
6284 velspeed = speed * 2 * scale;
6285 velocity *= velspeed;
6287 velocity.y += gravity * multiplier * 20;
6288 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6289 velspeed = findLength(&velocity);
6290 velocity = flatfacing * velspeed;
6293 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
6294 velocity -= facing * multiplier * speed * 700 * scale;
6295 velspeed = findLength(&velocity);
6296 if (velspeed > speed * 2 * scale) {
6297 velocity /= velspeed;
6298 velspeed = speed * 2 * scale;
6299 velocity *= velspeed;
6301 velocity.y += gravity * multiplier * 20;
6302 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6303 velspeed = findLength(&velocity);
6304 velocity = flatfacing * velspeed * -1;
6307 if (animTarget == fightsidestep) {
6308 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
6309 velspeed = findLength(&velocity);
6310 if (velspeed > speed * 12 * scale) {
6311 velocity /= velspeed;
6312 velspeed = speed * 12 * scale;
6313 velocity *= velspeed;
6315 velocity.y += gravity * multiplier * 20;
6316 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6317 velspeed = findLength(&velocity);
6318 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
6321 if (animTarget == staggerbackhighanim) {
6322 coords -= facing * multiplier * speed * 16 * scale;
6325 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
6326 coords -= facing * multiplier * speed * 20 * scale;
6330 if (animTarget == backhandspringanim) {
6331 //coords-=facing*multiplier*50*scale;
6332 velocity += facing * multiplier * speed * 700 * scale * -1;
6333 velspeed = findLength(&velocity);
6334 if (velspeed > speed * 50 * scale) {
6335 velocity /= velspeed;
6336 velspeed = speed * 50 * scale;
6337 velocity *= velspeed;
6339 velocity.y += gravity * multiplier * 20;
6340 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6341 velspeed = findLength(&velocity);
6342 velocity = flatfacing * velspeed * -1;
6344 if (animTarget == dodgebackanim) {
6345 //coords-=facing*multiplier*50*scale;
6346 velocity += facing * multiplier * speed * 700 * scale * -1;
6347 velspeed = findLength(&velocity);
6348 if (velspeed > speed * 60 * scale) {
6349 velocity /= velspeed;
6350 velspeed = speed * 60 * scale;
6351 velocity *= velspeed;
6353 velocity.y += gravity * multiplier * 20;
6354 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6355 velspeed = findLength(&velocity);
6356 velocity = flatfacing * velspeed * -1;
6359 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6360 velspeed = findLength(&velocity);
6363 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6364 velocity.y += gravity * multiplier;
6367 if (animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6368 coords += velocity * multiplier;
6371 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6372 if (isFlip() && targetFrame().label == 7) {
6376 if (animTarget == jumpupanim) {
6378 animTarget = getIdle();
6385 pause_sound(whooshsound);
6386 OPENAL_SetVolume(channels[whooshsound], 0);
6389 if (animTarget == jumpdownanim || isFlip()) {
6393 animTarget = getLanding();
6394 emit_sound_at(landsound, coords, 128.);
6397 addEnvSound(coords);
6402 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6403 coords.y += gravity * multiplier * 2;
6405 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
6406 coords.y = terrain.getHeight(coords.x, coords.z);
6410 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)) {
6411 velspeed = findLength(&velocity);
6413 if (velspeed < multiplier * 300 * scale) {
6416 velocity -= velocity / velspeed * multiplier * 300 * scale;
6418 if (velspeed > 5 && (isLanding() || isLandhard())) {
6419 skiddingdelay += multiplier;
6420 if (skiddelay <= 0) {
6421 FootLand(leftfoot, .5);
6422 FootLand(rightfoot, .5);
6431 velspeed = findLength(&velocity);
6433 if (velspeed > 5 && (isLanding() || isLandhard())) {
6434 skiddingdelay += multiplier;
6435 if (skiddelay <= 0) {
6436 FootLand(leftfoot, .5);
6437 FootLand(rightfoot, .5);
6445 if (skiddingdelay < 0) {
6446 skiddingdelay += multiplier;
6448 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
6450 if (!onterrain || environment == grassyenvironment) {
6451 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
6453 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
6457 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
6458 terrainnormal = victim->coords - coords;
6459 Normalise(&terrainnormal);
6460 targetyaw = -asin(0 - terrainnormal.x);
6461 targetyaw *= 360 / 6.28;
6462 if (terrainnormal.z < 0) {
6463 targetyaw = 180 - targetyaw;
6465 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
6468 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
6469 targetyaw = victim->targetyaw;
6471 if (animTarget == rabbittacklinganim) {
6472 coords = victim->coords;
6475 skeleton.oldfree = skeleton.free;
6479 midterrain.x = terrain.size * terrain.scale / 2;
6480 midterrain.z = terrain.size * terrain.scale / 2;
6481 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
6483 tempposit = coords - midterrain;
6485 Normalise(&tempposit);
6486 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
6487 coords.x = tempposit.x + midterrain.x;
6488 coords.z = tempposit.z + midterrain.z;
6493 * inverse kinematics helper function
6495 void IKHelper(Person* p, float interp)
6497 XYZ point, change, change2;
6498 float heightleft, heightright;
6500 // TODO: implement localToWorld and worldToLocal
6501 // but keep in mind it won't be the same math if player is ragdolled or something
6502 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
6503 // then comb through code for places where to use it
6505 // point = localToWorld(jointPos(leftfoot))
6506 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
6507 // adjust height of foot
6508 heightleft = terrain.getHeight(point.x, point.z) + .04;
6509 point.y = heightleft;
6510 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
6511 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
6512 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
6513 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
6514 // move ankle along with foot
6515 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
6516 // average knee pos between old and new pos
6517 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
6519 // do same as above for right leg
6520 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
6521 heightright = terrain.getHeight(point.x, point.z) + .04;
6522 point.y = heightright;
6523 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
6524 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
6525 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
6526 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
6527 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
6529 // fix up skeleton now that we've moved body parts?
6530 p->skeleton.DoConstraints(&p->coords, &p->scale);
6537 int Person::DrawSkeleton()
6539 int oldplayerdetail;
6540 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6541 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6551 glAlphaFunc(GL_GREATER, 0.0001);
6553 float terrainheight;
6555 if (!isnormal(yaw)) {
6558 if (!isnormal(tilt)) {
6561 if (!isnormal(tilt2)) {
6564 oldplayerdetail = playerdetail;
6566 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6569 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6572 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6578 if (playerdetail != oldplayerdetail) {
6580 normalsupdatedelay = 0;
6582 static float updatedelaychange;
6583 static float morphness;
6584 static float framemult;
6586 skeleton.FindForwards();
6587 if (howactive == typesittingwall) {
6588 skeleton.specialforward[1] = 0;
6589 skeleton.specialforward[1].z = 1;
6595 static int weaponattachmuscle;
6596 static int weaponrotatemuscle;
6597 static XYZ weaponpoint;
6598 static int start, endthing;
6599 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6600 if (!isSleeping() && !isSitting()) {
6601 // TODO: give these meaningful names
6602 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6603 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard() || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6605 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6607 if (creature == wolftype) {
6612 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6613 IKHelper(this, target);
6614 if (creature == wolftype) {
6615 IKHelper(this, target);
6619 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6620 IKHelper(this, 1 - target);
6621 if (creature == wolftype) {
6622 IKHelper(this, 1 - target);
6627 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())) {
6630 targetheadyaw = -targetyaw;
6631 targetheadpitch = 0;
6632 if (Animation::animations[animTarget].attack == 3) {
6633 targetheadyaw += 180;
6636 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6637 skeleton.drawmodel.vertex[i] = 0;
6638 skeleton.drawmodel.vertex[i].y = 999;
6640 for (int i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6641 skeleton.drawmodellow.vertex[i] = 0;
6642 skeleton.drawmodellow.vertex[i].y = 999;
6644 for (int i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6645 skeleton.drawmodelclothes.vertex[i] = 0;
6646 skeleton.drawmodelclothes.vertex[i].y = 999;
6648 for (unsigned int i = 0; i < skeleton.muscles.size(); i++) {
6649 // convenience renames
6650 const int p1 = skeleton.muscles[i].parent1->label;
6651 const int p2 = skeleton.muscles[i].parent2->label;
6653 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6658 if (p1 == righthand || p2 == righthand) {
6659 morphness = righthandmorphness;
6660 start = righthandmorphstart;
6661 endthing = righthandmorphend;
6663 if (p1 == lefthand || p2 == lefthand) {
6664 morphness = lefthandmorphness;
6665 start = lefthandmorphstart;
6666 endthing = lefthandmorphend;
6668 if (p1 == head || p2 == head) {
6669 morphness = headmorphness;
6670 start = headmorphstart;
6671 endthing = headmorphend;
6673 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6674 morphness = chestmorphness;
6675 start = chestmorphstart;
6676 endthing = chestmorphend;
6678 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6679 morphness = tailmorphness;
6680 start = tailmorphstart;
6681 endthing = tailmorphend;
6684 skeleton.FindRotationMuscle(i, animTarget);
6686 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6687 glMatrixMode(GL_MODELVIEW);
6690 if (!skeleton.free) {
6691 glRotatef(tilt2, 1, 0, 0);
6693 if (!skeleton.free) {
6694 glRotatef(tilt, 0, 0, 1);
6697 glTranslatef(mid.x, mid.y, mid.z);
6699 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6700 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6702 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6703 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6705 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6706 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6708 if (playerdetail || skeleton.free == 3) {
6709 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6710 XYZ& v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6711 XYZ& v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6712 glMatrixMode(GL_MODELVIEW);
6714 if (p1 == abdomen || p2 == abdomen) {
6715 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(1).x,
6716 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(1).y,
6717 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(1).z);
6719 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6720 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(2).x,
6721 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(2).y,
6722 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(2).z);
6724 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6725 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(3).x,
6726 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(3).y,
6727 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(3).z);
6729 if (p1 == head || p2 == head) {
6730 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(0).x,
6731 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(0).y,
6732 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(0).z);
6734 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6735 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6736 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6737 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6741 if (!playerdetail || skeleton.free == 3) {
6742 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6743 XYZ& v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6744 glMatrixMode(GL_MODELVIEW);
6746 if (p1 == abdomen || p2 == abdomen) {
6747 glTranslatef(v0.x * getProportion(1).x,
6748 v0.y * getProportion(1).y,
6749 v0.z * getProportion(1).z);
6751 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6752 glTranslatef(v0.x * getProportion(2).x,
6753 v0.y * getProportion(2).y,
6754 v0.z * getProportion(2).z);
6756 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6757 glTranslatef(v0.x * getProportion(3).x,
6758 v0.y * getProportion(3).y,
6759 v0.z * getProportion(3).z);
6761 if (p1 == head || p2 == head) {
6762 glTranslatef(v0.x * getProportion(0).x,
6763 v0.y * getProportion(0).y,
6764 v0.z * getProportion(0).z);
6767 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6768 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6769 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6770 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6776 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6777 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6779 glMatrixMode(GL_MODELVIEW);
6782 if (!skeleton.free) {
6783 glRotatef(tilt2, 1, 0, 0);
6785 if (!skeleton.free) {
6786 glRotatef(tilt, 0, 0, 1);
6788 glTranslatef(mid.x, mid.y, mid.z);
6789 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6790 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6792 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6793 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6795 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6796 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6798 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6799 XYZ& v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6800 glMatrixMode(GL_MODELVIEW);
6802 if (p1 == abdomen || p2 == abdomen) {
6803 glTranslatef(v0.x * getProportion(1).x,
6804 v0.y * getProportion(1).y,
6805 v0.z * getProportion(1).z);
6807 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6808 glTranslatef(v0.x * getProportion(2).x,
6809 v0.y * getProportion(2).y,
6810 v0.z * getProportion(2).z);
6812 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6813 glTranslatef(v0.x * getProportion(3).x,
6814 v0.y * getProportion(3).y,
6815 v0.z * getProportion(3).z);
6817 if (p1 == head || p2 == head) {
6818 glTranslatef(v0.x * getProportion(0).x,
6819 v0.y * getProportion(0).y,
6820 v0.z * getProportion(0).z);
6822 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6823 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6824 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6825 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6830 updatedelay = 1 + (float)(Random() % 100) / 1000;
6832 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6833 normalsupdatedelay = 1;
6834 if (playerdetail || skeleton.free == 3) {
6835 skeleton.drawmodel.CalculateNormals(0);
6837 if (!playerdetail || skeleton.free == 3) {
6838 skeleton.drawmodellow.CalculateNormals(0);
6840 if (skeleton.clothes) {
6841 skeleton.drawmodelclothes.CalculateNormals(0);
6844 if (playerdetail || skeleton.free == 3) {
6845 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6847 if (!playerdetail || skeleton.free == 3) {
6848 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6850 if (skeleton.clothes) {
6851 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6856 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6857 if (updatedelaychange > -realmultiplier * 30) {
6858 updatedelaychange = -realmultiplier * 30;
6860 if (updatedelaychange > -framemult * 4) {
6861 updatedelaychange = -framemult * 4;
6863 if (skeleton.free == 1) {
6864 updatedelaychange *= 6;
6867 updatedelaychange *= 8;
6869 updatedelay += updatedelaychange;
6871 glMatrixMode(GL_MODELVIEW);
6873 glTranslatef(coords.x, coords.y - .02, coords.z);
6874 if (!skeleton.free) {
6875 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6876 glRotatef(yaw, 0, 1, 0);
6880 glColor4f(.4, 1, .4, 1);
6881 glDisable(GL_LIGHTING);
6882 glDisable(GL_TEXTURE_2D);
6885 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6886 XYZ& v0 = skeleton.drawmodel.vertex[i];
6887 glVertex3f(v0.x, v0.y, v0.z);
6894 for (unsigned int i = 0; i < skeleton.drawmodel.Triangles.size(); i++) {
6895 const XYZ& v0 = skeleton.drawmodel.getTriangleVertex(i, 0);
6896 const XYZ& v1 = skeleton.drawmodel.getTriangleVertex(i, 1);
6897 const XYZ& v2 = skeleton.drawmodel.getTriangleVertex(i, 2);
6898 glVertex3f(v0.x, v0.y, v0.z);
6899 glVertex3f(v1.x, v1.y, v1.z);
6900 glVertex3f(v1.x, v1.y, v1.z);
6901 glVertex3f(v2.x, v2.y, v2.z);
6902 glVertex3f(v2.x, v2.y, v2.z);
6903 glVertex3f(v0.x, v0.y, v0.z);
6910 terrainlight = terrain.getLighting(coords.x, coords.z);
6911 distance = distsq(&viewer, &coords);
6912 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6917 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6918 if (terrainheight < 1) {
6921 if (terrainheight > 1.7) {
6922 terrainheight = 1.7;
6925 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6926 glDisable(GL_BLEND);
6927 glAlphaFunc(GL_GREATER, 0.0001);
6928 glEnable(GL_TEXTURE_2D);
6930 glDisable(GL_TEXTURE_2D);
6931 glColor4f(.7, .35, 0, .5);
6933 glEnable(GL_LIGHTING);
6936 if (Tutorial::active && id != 0) {
6937 glColor4f(.7, .7, .7, 0.6);
6939 glEnable(GL_LIGHTING);
6941 if (canattack && cananger) {
6942 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6943 glDisable(GL_TEXTURE_2D);
6944 glColor4f(1, 0, 0, 0.8);
6947 glMatrixMode(GL_TEXTURE);
6949 glTranslatef(0, -smoketex, 0);
6950 glTranslatef(-smoketex, 0, 0);
6954 if (Tutorial::active && (id != 0)) {
6955 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6957 skeleton.drawmodel.draw();
6961 if (!playerdetail) {
6962 if (Tutorial::active && (id != 0)) {
6963 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6965 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6969 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed)) {
6970 if (Tutorial::active && id != 0) {
6972 glMatrixMode(GL_MODELVIEW);
6973 glEnable(GL_TEXTURE_2D);
6974 glColor4f(.7, .7, .7, 0.6);
6976 glEnable(GL_LIGHTING);
6978 if (canattack && cananger) {
6979 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6980 glDisable(GL_TEXTURE_2D);
6981 glColor4f(1, 0, 0, 0.8);
6984 glMatrixMode(GL_TEXTURE);
6986 glTranslatef(0, -smoketex * .6, 0);
6987 glTranslatef(smoketex * .6, 0, 0);
6990 if (Tutorial::active && (id != 0)) {
6991 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6993 skeleton.drawmodel.draw();
6997 if (!playerdetail) {
6998 if (Tutorial::active && (id != 0)) {
6999 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
7001 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
7007 if (Tutorial::active && id != 0) {
7009 glMatrixMode(GL_MODELVIEW);
7010 glEnable(GL_TEXTURE_2D);
7012 if (skeleton.clothes) {
7016 skeleton.drawmodelclothes.draw();
7019 skeleton.drawmodelclothes.drawimmediate();
7026 if (num_weapons > 0) {
7027 for (k = 0; k < num_weapons; k++) {
7028 int i = weaponids[k];
7029 if (weaponactive == k) {
7030 if (weapons[i].getType() != staff) {
7031 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7032 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
7033 weaponattachmuscle = j;
7036 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7037 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) {
7038 weaponrotatemuscle = j;
7041 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
7042 if (creature == wolftype) {
7043 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
7046 if (weapons[i].getType() == staff) {
7047 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7048 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
7049 weaponattachmuscle = j;
7052 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7053 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) {
7054 weaponrotatemuscle = j;
7057 //weaponpoint=jointPos(rightwrist);
7058 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
7059 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
7060 XYZ tempnormthing, vec1, vec2;
7061 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
7062 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
7063 CrossProduct(&vec1, &vec2, &tempnormthing);
7064 Normalise(&tempnormthing);
7065 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim) {
7066 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
7070 if (weaponactive != k && weaponstuck != k) {
7071 if (weapons[i].getType() == knife) {
7072 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
7074 if (weapons[i].getType() == sword) {
7075 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
7077 if (weapons[i].getType() == staff) {
7078 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
7080 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7081 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) {
7082 weaponrotatemuscle = j;
7086 if (weaponstuck == k) {
7087 if (weaponstuckwhere == 0) {
7088 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
7090 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
7092 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7093 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) {
7094 weaponrotatemuscle = j;
7098 if (skeleton.free) {
7099 weapons[i].position = weaponpoint * scale + coords;
7100 weapons[i].bigrotation = 0;
7101 weapons[i].bigtilt = 0;
7102 weapons[i].bigtilt2 = 0;
7104 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;
7105 weapons[i].bigrotation = yaw;
7106 weapons[i].bigtilt = tilt;
7107 weapons[i].bigtilt2 = tilt2;
7109 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
7110 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
7111 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
7112 if (weaponactive == k) {
7113 if (weapons[i].getType() == knife) {
7114 weapons[i].smallrotation = 180;
7115 weapons[i].smallrotation2 = 0;
7116 if (isCrouch() || wasCrouch()) {
7117 weapons[i].smallrotation2 = 20;
7119 if (animTarget == hurtidleanim) {
7120 weapons[i].smallrotation2 = 50;
7122 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
7123 XYZ temppoint1, temppoint2;
7126 temppoint1 = jointPos(righthand);
7127 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7128 distance = findDistance(&temppoint1, &temppoint2);
7129 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7130 weapons[i].rotation2 *= 360 / 6.28;
7133 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7134 weapons[i].rotation1 *= 360 / 6.28;
7135 weapons[i].rotation3 = 0;
7136 weapons[i].smallrotation = -90;
7137 weapons[i].smallrotation2 = 0;
7138 if (temppoint1.x > temppoint2.x) {
7139 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7142 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
7143 XYZ temppoint1, temppoint2;
7146 temppoint1 = jointPos(righthand);
7147 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7148 distance = findDistance(&temppoint1, &temppoint2);
7149 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7150 weapons[i].rotation2 *= 360 / 6.28;
7153 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7154 weapons[i].rotation1 *= 360 / 6.28;
7155 weapons[i].rotation3 = 0;
7156 weapons[i].smallrotation = 90;
7157 weapons[i].smallrotation2 = 0;
7158 if (temppoint1.x > temppoint2.x) {
7159 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7162 if (animTarget == knifethrowanim) {
7163 weapons[i].smallrotation = 90;
7164 //weapons[i].smallrotation2=-90;
7165 weapons[i].smallrotation2 = 0;
7166 weapons[i].rotation1 = 0;
7167 weapons[i].rotation2 = 0;
7168 weapons[i].rotation3 = 0;
7170 if (animTarget == knifesneakattackanim && frameTarget < 5) {
7171 weapons[i].smallrotation = -90;
7172 weapons[i].rotation1 = 0;
7173 weapons[i].rotation2 = 0;
7174 weapons[i].rotation3 = 0;
7177 if (weapons[i].getType() == sword) {
7178 weapons[i].smallrotation = 0;
7179 weapons[i].smallrotation2 = 0;
7180 if (animTarget == knifethrowanim) {
7181 weapons[i].smallrotation = -90;
7182 weapons[i].smallrotation2 = 0;
7183 weapons[i].rotation1 = 0;
7184 weapons[i].rotation2 = 0;
7185 weapons[i].rotation3 = 0;
7187 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)) {
7188 XYZ temppoint1, temppoint2;
7191 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
7192 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7193 distance = findDistance(&temppoint1, &temppoint2);
7194 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7195 weapons[i].rotation2 *= 360 / 6.28;
7198 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7199 weapons[i].rotation1 *= 360 / 6.28;
7200 weapons[i].rotation3 = 0;
7201 weapons[i].smallrotation = 90;
7202 weapons[i].smallrotation2 = 0;
7203 if (temppoint1.x > temppoint2.x) {
7204 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7208 if (weapons[i].getType() == staff) {
7209 weapons[i].smallrotation = 100;
7210 weapons[i].smallrotation2 = 0;
7211 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
7212 XYZ temppoint1, temppoint2;
7215 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
7216 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7217 distance = findDistance(&temppoint1, &temppoint2);
7218 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7219 weapons[i].rotation2 *= 360 / 6.28;
7222 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7223 weapons[i].rotation1 *= 360 / 6.28;
7224 weapons[i].rotation3 = 0;
7225 weapons[i].smallrotation = 90;
7226 weapons[i].smallrotation2 = 0;
7227 if (temppoint1.x > temppoint2.x) {
7228 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7233 if (weaponactive != k && weaponstuck != k) {
7234 if (weapons[i].getType() == knife) {
7235 weapons[i].smallrotation = -70;
7236 weapons[i].smallrotation2 = 10;
7238 if (weapons[i].getType() == sword) {
7239 weapons[i].smallrotation = -100;
7240 weapons[i].smallrotation2 = -8;
7242 if (weapons[i].getType() == staff) {
7243 weapons[i].smallrotation = -100;
7244 weapons[i].smallrotation2 = -8;
7247 if (weaponstuck == k) {
7248 if (weaponstuckwhere == 0) {
7249 weapons[i].smallrotation = 180;
7251 weapons[i].smallrotation = 0;
7253 weapons[i].smallrotation2 = 10;
7260 if (skeleton.free) {
7263 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump()) {
7266 if (animCurrent != animTarget) {
7269 if (skeleton.free == 2) {
7278 int Person::SphereCheck(XYZ* p1, float radius, XYZ* p, XYZ* move, float* rotate, Model* model)
7280 static float distance;
7281 static float olddistance;
7282 static int intersecting;
7283 static int firstintersecting;
7286 static XYZ start, end;
7287 static float slopethreshold = -.4;
7289 firstintersecting = -1;
7293 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius) {
7297 *p1 = DoRotation(*p1, 0, -*rotate, 0);
7299 for (int i = 0; i < 4; i++) {
7300 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7301 if (model->Triangles[j].facenormal.y <= slopethreshold) {
7303 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)));
7304 if (distance < radius) {
7305 point = *p1 - model->Triangles[j].facenormal * distance;
7306 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]])) {
7309 if (!intersecting) {
7310 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7311 &model->vertex[model->Triangles[j].vertex[1]],
7314 if (!intersecting) {
7315 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
7316 &model->vertex[model->Triangles[j].vertex[2]],
7319 if (!intersecting) {
7320 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7321 &model->vertex[model->Triangles[j].vertex[2]],
7325 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7329 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)) {
7330 p1->y = point.y + radius;
7331 if ((animTarget == jumpdownanim || isFlip())) {
7332 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4)) {
7336 if (animTarget == jumpupanim) {
7338 animTarget = getIdle();
7345 pause_sound(whooshsound);
7346 OPENAL_SetVolume(channels[whooshsound], 0);
7349 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
7353 animTarget = getLanding();
7354 emit_sound_at(landsound, coords, 128.);
7357 addEnvSound(coords);
7364 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7365 olddistance = distance;
7366 firstintersecting = j;
7371 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7372 if (model->Triangles[j].facenormal.y > slopethreshold) {
7375 start.y -= radius / 4;
7376 XYZ& v0 = model->vertex[model->Triangles[j].vertex[0]];
7377 XYZ& v1 = model->vertex[model->Triangles[j].vertex[1]];
7378 XYZ& v2 = model->vertex[model->Triangles[j].vertex[2]];
7379 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)));
7380 if (distance < radius * .5) {
7381 point = start - model->Triangles[j].facenormal * distance;
7382 if (PointInTriangle(&point, model->Triangles[j].facenormal, &v0, &v1, &v2)) {
7385 if (!intersecting) {
7386 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
7388 if (!intersecting) {
7389 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7391 if (!intersecting) {
7392 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7395 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7396 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
7398 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;
7399 if (findLengthfast(&start) < findLengthfast(&velocity)) {
7403 *p1 += model->Triangles[j].facenormal * (distance - radius * .5);
7406 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7407 olddistance = distance;
7408 firstintersecting = j;
7415 *p = DoRotation(*p, 0, *rotate, 0);
7419 *p1 = DoRotation(*p1, 0, *rotate, 0);
7422 return firstintersecting;
7425 int findPathDist(int start, int end)
7430 unsigned int smallestcount = 1000;
7431 for (char i = 0; i < 50; i++) {
7432 unsigned int count = 0;
7437 while (last != end && count < 30) {
7439 for (int j = 0; j < Game::numpathpoints; j++) {
7440 if (j != last && j != last2 && j != last3 && j != last4) {
7442 if (Game::numpathpointconnect[j]) {
7443 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7444 if (Game::pathpointconnect[j][k] == last) {
7450 if (Game::numpathpointconnect[last]) {
7451 for (int k = 0; k < Game::numpathpointconnect[last]; k++) {
7452 if (Game::pathpointconnect[last][k] == j) {
7459 if (closest == -1 || Random() % 2 == 0) {
7471 if (count < smallestcount) {
7472 smallestcount = count;
7475 return smallestcount;
7478 void Person::takeWeapon(int weaponId)
7481 weapons[weaponId].owner = id;
7482 if (num_weapons > 0) {
7483 weaponids[num_weapons] = weaponids[0];
7486 weaponids[0] = weaponId;
7489 void Person::addClothes()
7491 if (numclothes > 0) {
7492 for (int i = 0; i < numclothes; i++) {
7499 bool Person::addClothes(const int& clothesId)
7502 const std::string fileName = clothes[clothesId];
7504 GLubyte* array = &skeleton.skinText[0];
7508 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
7513 float tintr = clothestintr[clothesId];
7514 float tintg = clothestintg[clothesId];
7515 float tintb = clothestintb[clothesId];
7537 int bytesPerPixel = texture.bpp / 8;
7541 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
7542 if (bytesPerPixel == 3) {
7544 } else if ((i + 1) % 4 == 0) {
7545 alphanum = texture.data[i];
7547 if ((i + 1) % 4 || bytesPerPixel == 3) {
7549 texture.data[i] *= tintr;
7552 texture.data[i] *= tintg;
7555 texture.data[i] *= tintb;
7557 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
7569 if (aitype != playercontrolled && !Dialog::inDialog()) {
7571 //disable movement in editor
7572 if (Game::editorenabled) {
7577 if (distsqflat(&Person::players[0]->coords, &coords) < 30 &&
7578 Person::players[0]->coords.y > coords.y + 2 &&
7579 !Person::players[0]->onterrain) {
7584 if (aitype == pathfindtype) {
7585 if (finalpathfindpoint == -1) {
7586 float closestdistance;
7587 float tempdist = 0.0f;
7591 closestdistance = -1;
7592 for (int j = 0; j < Game::numpathpoints; j++) {
7593 if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) {
7594 closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]);
7596 finaltarget = Game::pathpoint[j];
7599 finalpathfindpoint = closest;
7600 for (int j = 0; j < Game::numpathpoints; j++) {
7601 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7602 DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7603 if (sq(tempdist) < closestdistance) {
7604 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7605 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7606 closestdistance = sq(tempdist);
7608 finaltarget = colpoint;
7613 finalpathfindpoint = closest;
7615 if (targetpathfindpoint == -1) {
7616 float closestdistance;
7617 float tempdist = 0.0f;
7621 closestdistance = -1;
7622 if (lastpathfindpoint == -1) {
7623 for (int j = 0; j < Game::numpathpoints; j++) {
7624 if (j != lastpathfindpoint) {
7625 if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) {
7626 closestdistance = distsq(&coords, &Game::pathpoint[j]);
7631 targetpathfindpoint = closest;
7632 for (int j = 0; j < Game::numpathpoints; j++) {
7633 if (j != lastpathfindpoint) {
7634 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7635 DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7636 if (sq(tempdist) < closestdistance) {
7637 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7638 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7639 closestdistance = sq(tempdist);
7646 targetpathfindpoint = closest;
7648 for (int j = 0; j < Game::numpathpoints; j++) {
7649 if (j != lastpathfindpoint &&
7650 j != lastpathfindpoint2 &&
7651 j != lastpathfindpoint3 &&
7652 j != lastpathfindpoint4) {
7654 if (Game::numpathpointconnect[j]) {
7655 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7656 if (Game::pathpointconnect[j][k] == lastpathfindpoint) {
7662 if (Game::numpathpointconnect[lastpathfindpoint]) {
7663 for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++) {
7664 if (Game::pathpointconnect[lastpathfindpoint][k] == j) {
7671 tempdist = findPathDist(j, finalpathfindpoint);
7672 if (closest == -1 || tempdist < closestdistance) {
7673 closestdistance = tempdist;
7679 targetpathfindpoint = closest;
7682 losupdatedelay -= multiplier;
7684 targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]);
7685 lookyaw = targetyaw;
7687 //reached target point
7688 if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) {
7689 lastpathfindpoint4 = lastpathfindpoint3;
7690 lastpathfindpoint3 = lastpathfindpoint2;
7691 lastpathfindpoint2 = lastpathfindpoint;
7692 lastpathfindpoint = targetpathfindpoint;
7693 if (lastpathfindpoint2 == -1) {
7694 lastpathfindpoint2 = lastpathfindpoint;
7696 if (lastpathfindpoint3 == -1) {
7697 lastpathfindpoint3 = lastpathfindpoint2;
7699 if (lastpathfindpoint4 == -1) {
7700 lastpathfindpoint4 = lastpathfindpoint3;
7702 targetpathfindpoint = -1;
7704 if (distsqflat(&coords, &finalfinaltarget) <
7705 distsqflat(&coords, &finaltarget) ||
7706 distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) ||
7707 lastpathfindpoint == finalpathfindpoint) {
7708 aitype = passivetype;
7719 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7720 targetyaw += 90 * (whichdirection * 2 - 1);
7723 if (collided < 1 || animTarget != jumpupanim) {
7726 if ((collided > .8 && jumppower >= 5)) {
7730 if ((!Tutorial::active || cananger) &&
7732 !Person::players[0]->dead &&
7733 distsq(&coords, &Person::players[0]->coords) < 400 &&
7735 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7736 Animation::animations[Person::players[0]->animTarget].height != lowheight &&
7737 !Game::editorenabled &&
7738 (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain)) {
7739 aitype = attacktypecutoff;
7741 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7742 Animation::animations[Person::players[0]->animTarget].height == highheight &&
7743 !Game::editorenabled) {
7744 aitype = attacktypecutoff;
7747 if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7748 losupdatedelay = .2;
7749 for (unsigned j = 0; j < Person::players.size(); j++) {
7750 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7751 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7752 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7753 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7754 if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain) {
7755 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) ||
7756 (Person::players[j]->animTarget == hanganim &&
7757 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7758 aitype = searchtype;
7760 lastseen = Person::players[j]->coords;
7771 if (aitype == attacktypecutoff && Game::musictype != 2) {
7772 if (creature != wolftype) {
7779 if (aitype != passivetype && Game::leveltime > .5) {
7780 howactive = typeactive;
7783 if (aitype == passivetype) {
7784 aiupdatedelay -= multiplier;
7785 losupdatedelay -= multiplier;
7786 lastseentime += multiplier;
7787 pausetime -= multiplier;
7788 if (lastseentime > 1) {
7792 if (aiupdatedelay < 0) {
7793 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7794 targetyaw = roughDirectionTo(coords, waypoints[waypoint]);
7795 lookyaw = targetyaw;
7796 aiupdatedelay = .05;
7798 if (distsqflat(&coords, &waypoints[waypoint]) < 1) {
7799 if (waypointtype[waypoint] == wppause) {
7803 if (waypoint > numwaypoints - 1) {
7809 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7821 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7822 if (!avoidsomething) {
7823 targetyaw += 90 * (whichdirection * 2 - 1);
7825 XYZ leftpos, rightpos;
7826 float leftdist, rightdist;
7827 leftpos = coords + DoRotation(facing, 0, 90, 0);
7828 rightpos = coords - DoRotation(facing, 0, 90, 0);
7829 leftdist = distsq(&leftpos, &avoidwhere);
7830 rightdist = distsq(&rightpos, &avoidwhere);
7831 if (leftdist < rightdist) {
7839 if (collided < 1 || animTarget != jumpupanim) {
7842 if ((collided > .8 && jumppower >= 5)) {
7847 if (!Game::editorenabled) {
7848 if (howactive <= typesleeping) {
7849 if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile) {
7850 for (int j = 0; j < numenvsounds; j++) {
7851 float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
7852 if (vol > 0 && distsq(&coords, &envsound[j]) < 2 * (vol + vol * (creature == rabbittype) * 3)) {
7853 aitype = attacktypecutoff;
7859 if (aitype != passivetype) {
7860 if (howactive == typesleeping) {
7861 setTargetAnimation(getupfromfrontanim);
7863 howactive = typeactive;
7867 if (howactive < typesleeping &&
7868 ((!Tutorial::active || cananger) && hostile) &&
7869 !Person::players[0]->dead &&
7870 distsq(&coords, &Person::players[0]->coords) < 400 &&
7872 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7873 Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled) {
7874 aitype = attacktypecutoff;
7876 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7877 Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled) {
7878 aitype = attacktypecutoff;
7882 if (creature == wolftype) {
7884 for (unsigned j = 0; j < Person::players.size(); j++) {
7885 if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
7886 float smelldistance = 50;
7887 if (j == 0 && Person::players[j]->num_weapons > 0) {
7888 if (weapons[Person::players[j]->weaponids[0]].bloody) {
7889 smelldistance = 100;
7891 if (Person::players[j]->num_weapons == 2) {
7892 if (weapons[Person::players[j]->weaponids[1]].bloody) {
7893 smelldistance = 100;
7898 smelldistance = 100;
7900 windsmell = windvector;
7901 Normalise(&windsmell);
7902 windsmell = windsmell * 2 + Person::players[j]->coords;
7903 if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled) {
7904 aitype = attacktypecutoff;
7910 if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7911 losupdatedelay = .2;
7912 for (unsigned j = 0; j < Person::players.size(); j++) {
7913 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7914 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7915 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7916 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7917 if ((-1 == Object::checkcollide(
7918 DoRotation(jointPos(head), 0, yaw, 0) *
7921 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0) *
7922 Person::players[j]->scale +
7923 Person::players[j]->coords) &&
7924 !Person::players[j]->isWallJump()) ||
7925 (Person::players[j]->animTarget == hanganim &&
7926 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7928 if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight) {
7937 if (lastseentime <= 0) {
7938 aitype = searchtype;
7940 lastseen = Person::players[j]->coords;
7948 if (aitype == attacktypecutoff && Game::musictype != 2) {
7949 if (creature != wolftype) {
7953 if (creature == wolftype) {
7963 if (aitype == searchtype) {
7964 aiupdatedelay -= multiplier;
7965 losupdatedelay -= multiplier;
7967 lastseentime -= multiplier;
7969 lastchecktime -= multiplier;
7971 if (isRun() && !onground) {
7972 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7973 XYZ test2 = coords + facing;
7975 XYZ test = coords + facing;
7977 j = Object::checkcollide(test2, test, laststanding);
7979 j = Object::checkcollide(test2, test);
7983 setTargetAnimation(getStop());
7986 //aitype=passivetype;
7987 aitype = pathfindtype;
7988 finalfinaltarget = waypoints[waypoint];
7989 finalpathfindpoint = -1;
7990 targetpathfindpoint = -1;
7991 lastpathfindpoint = -1;
7992 lastpathfindpoint2 = -1;
7993 lastpathfindpoint3 = -1;
7994 lastpathfindpoint4 = -1;
8000 //check out last seen location
8001 if (aiupdatedelay < 0) {
8002 targetyaw = roughDirectionTo(coords, lastseen);
8003 lookyaw = targetyaw;
8004 aiupdatedelay = .05;
8007 if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) {
8010 lastseen.x += (float(Random() % 100) - 50) / 25;
8011 lastseen.z += (float(Random() % 100) - 50) / 25;
8022 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8023 if (!avoidsomething) {
8024 targetyaw += 90 * (whichdirection * 2 - 1);
8026 XYZ leftpos, rightpos;
8027 float leftdist, rightdist;
8028 leftpos = coords + DoRotation(facing, 0, 90, 0);
8029 rightpos = coords - DoRotation(facing, 0, 90, 0);
8030 leftdist = distsq(&leftpos, &avoidwhere);
8031 rightdist = distsq(&rightpos, &avoidwhere);
8032 if (leftdist < rightdist) {
8040 if (collided < 1 || animTarget != jumpupanim) {
8043 if ((collided > .8 && jumppower >= 5)) {
8047 if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile)) {
8048 for (int k = 0; k < numenvsounds; k++) {
8049 if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) {
8050 aitype = attacktypecutoff;
8055 if (!Person::players[0]->dead &&
8056 losupdatedelay < 0 &&
8057 !Game::editorenabled &&
8059 ((!Tutorial::active || cananger) && hostile)) {
8060 losupdatedelay = .2;
8061 if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) {
8062 aitype = attacktypecutoff;
8065 if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight) {
8066 //TODO: factor out canSeePlayer()
8067 if (distsq(&coords, &Person::players[0]->coords) < 400) {
8068 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
8069 if ((Object::checkcollide(
8070 DoRotation(jointPos(head), 0, yaw, 0) *
8073 DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0) *
8074 Person::players[0]->scale +
8075 Person::players[0]->coords) == -1) ||
8076 (Person::players[0]->animTarget == hanganim && normaldotproduct(Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) {
8077 /* //TODO: changed j to 0 on a whim, make sure this is correct
8078 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
8079 Person::players[j]->facing,coords-Person::players[j]->coords)<0)
8081 aitype = attacktypecutoff;
8089 if (lastseentime < 0) {
8090 //aitype=passivetype;
8092 aitype = pathfindtype;
8093 finalfinaltarget = waypoints[waypoint];
8094 finalpathfindpoint = -1;
8095 targetpathfindpoint = -1;
8096 lastpathfindpoint = -1;
8097 lastpathfindpoint2 = -1;
8098 lastpathfindpoint3 = -1;
8099 lastpathfindpoint4 = -1;
8103 if (aitype != gethelptype) {
8107 //get help from buddies
8108 if (aitype == gethelptype) {
8109 runninghowlong += multiplier;
8110 aiupdatedelay -= multiplier;
8112 if (aiupdatedelay < 0 || ally == 0) {
8116 //TODO: factor out closest search somehow
8119 float closestdist = -1;
8120 for (unsigned k = 0; k < Person::players.size(); k++) {
8121 if ((k != id) && (k != 0) && !Person::players[k]->dead &&
8122 (Person::players[k]->howactive < typedead1) &&
8123 !Person::players[k]->skeleton.free &&
8124 (Person::players[k]->aitype == passivetype)) {
8125 float distance = distsq(&coords, &Person::players[k]->coords);
8126 if (closestdist == -1 || distance < closestdist) {
8127 closestdist = distance;
8132 if (closest != -1) {
8137 lastseen = Person::players[0]->coords;
8143 XYZ facing = coords;
8144 XYZ flatfacing = Person::players[ally]->coords;
8145 facing.y += jointPos(head).y * scale;
8146 flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale;
8147 if (-1 != Object::checkcollide(facing, flatfacing)) {
8151 //no available ally, run back to player
8153 Person::players[ally]->skeleton.free ||
8154 Person::players[ally]->aitype != passivetype ||
8155 lastseentime <= 0) {
8156 aitype = searchtype;
8162 targetyaw = roughDirectionTo(coords, Person::players[ally]->coords);
8163 lookyaw = targetyaw;
8164 aiupdatedelay = .05;
8167 if (distsqflat(&coords, &Person::players[ally]->coords) < 3) {
8168 aitype = searchtype;
8170 Person::players[ally]->aitype = searchtype;
8171 if (Person::players[ally]->lastseentime < lastseentime) {
8172 Person::players[ally]->lastseen = lastseen;
8173 Person::players[ally]->lastseentime = lastseentime;
8174 Person::players[ally]->lastchecktime = lastchecktime;
8178 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8179 if (!avoidsomething) {
8180 targetyaw += 90 * (whichdirection * 2 - 1);
8182 XYZ leftpos, rightpos;
8183 float leftdist, rightdist;
8184 leftpos = coords + DoRotation(facing, 0, 90, 0);
8185 rightpos = coords - DoRotation(facing, 0, 90, 0);
8186 leftdist = distsq(&leftpos, &avoidwhere);
8187 rightdist = distsq(&rightpos, &avoidwhere);
8188 if (leftdist < rightdist) {
8203 if (collided < 1 || animTarget != jumpupanim) {
8206 if (collided > .8 && jumppower >= 5) {
8211 //retreiving a weapon on the ground
8212 if (aitype == getweapontype) {
8213 aiupdatedelay -= multiplier;
8214 lastchecktime -= multiplier;
8216 if (aiupdatedelay < 0) {
8222 float closestdist = -1;
8223 for (unsigned k = 0; k < weapons.size(); k++) {
8224 if (weapons[k].owner == -1) {
8225 float distance = distsq(&coords, &weapons[k].position);
8226 if (closestdist == -1 || distance < closestdist) {
8227 closestdist = distance;
8232 if (closest != -1) {
8241 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile)) {
8242 if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) {
8243 aitype = attacktypecutoff;
8247 if (!Person::players[0]->dead) {
8249 if (weapons[ally].owner != -1 ||
8250 distsq(&coords, &weapons[ally].position) > 16) {
8251 aitype = attacktypecutoff;
8254 //TODO: factor these out as moveToward()
8255 targetyaw = roughDirectionTo(coords, weapons[ally].position);
8256 lookyaw = targetyaw;
8257 aiupdatedelay = .05;
8260 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8261 if (!avoidsomething) {
8262 targetyaw += 90 * (whichdirection * 2 - 1);
8264 XYZ leftpos, rightpos;
8265 float leftdist, rightdist;
8266 leftpos = coords + DoRotation(facing, 0, 90, 0);
8267 rightpos = coords - DoRotation(facing, 0, 90, 0);
8268 leftdist = distsq(&leftpos, &avoidwhere);
8269 rightdist = distsq(&rightpos, &avoidwhere);
8270 if (leftdist < rightdist) {
8286 if (animTarget != crouchremoveknifeanim &&
8287 animTarget != removeknifeanim) {
8288 throwtogglekeydown = 0;
8292 if (collided < 1 || animTarget != jumpupanim) {
8295 if ((collided > .8 && jumppower >= 5)) {
8300 if (aitype == attacktypecutoff) {
8301 aiupdatedelay -= multiplier;
8302 //dodge or reverse rabbit kicks, knife throws, flips
8303 if (damage < damagetolerance * 2 / 3) {
8304 if ((Person::players[0]->animTarget == rabbitkickanim ||
8305 Person::players[0]->animTarget == knifethrowanim ||
8306 (Person::players[0]->isFlip() &&
8307 normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) &&
8308 !Person::players[0]->skeleton.free &&
8309 (aiupdatedelay < .1)) {
8314 if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
8315 if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
8316 if (isIdle() || isCrouch() || isRun() || isFlip()) {
8317 if (abs(Random() % 2) == 0) {
8318 setTargetAnimation(backhandspringanim);
8320 setTargetAnimation(rollanim);
8322 targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
8325 if (animTarget == jumpupanim || animTarget == jumpdownanim) {
8326 setTargetAnimation(flipanim);
8331 aiupdatedelay = .02;
8334 //get confused by flips
8335 if (Person::players[0]->isFlip() &&
8336 !Person::players[0]->skeleton.free &&
8337 Person::players[0]->animTarget != walljumprightkickanim &&
8338 Person::players[0]->animTarget != walljumpleftkickanim) {
8339 if (distsq(&Person::players[0]->coords, &coords) < 25) {
8340 if ((1 - damage / damagetolerance) > .5) {
8345 //go for weapon on the ground
8346 if (wentforweapon < 3) {
8347 for (unsigned k = 0; k < weapons.size(); k++) {
8348 if (creature != wolftype) {
8349 if (num_weapons == 0 &&
8350 weapons[k].owner == -1 &&
8351 weapons[k].velocity.x == 0 &&
8352 weapons[k].velocity.z == 0 &&
8353 weapons[k].velocity.y == 0) {
8354 if (distsq(&coords, &weapons[k].position) < 16) {
8357 aitype = getweapontype;
8364 //dodge/reverse walljump kicks
8365 if (damage < damagetolerance / 2) {
8366 if (Animation::animations[animTarget].height != highheight) {
8367 if (damage < damagetolerance * .5 &&
8368 ((Person::players[0]->animTarget == walljumprightkickanim ||
8369 Person::players[0]->animTarget == walljumpleftkickanim) &&
8370 ((aiupdatedelay < .15 &&
8372 (aiupdatedelay < .08 &&
8373 difficulty != 2)))) {
8378 //walked off a ledge (?)
8379 if (isRun() && !onground) {
8380 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
8381 XYZ test2 = coords + facing;
8383 XYZ test = coords + facing;
8385 j = Object::checkcollide(test2, test, laststanding);
8387 j = Object::checkcollide(test2, test);
8391 setTargetAnimation(getStop());
8394 aitype = pathfindtype;
8395 finalfinaltarget = waypoints[waypoint];
8396 finalpathfindpoint = -1;
8397 targetpathfindpoint = -1;
8398 lastpathfindpoint = -1;
8399 lastpathfindpoint2 = -1;
8400 lastpathfindpoint3 = -1;
8401 lastpathfindpoint4 = -1;
8407 //lose sight of player in the air (?)
8408 if (Person::players[0]->coords.y > coords.y + 5 &&
8409 Animation::animations[Person::players[0]->animTarget].height != highheight &&
8410 !Person::players[0]->onterrain) {
8411 aitype = pathfindtype;
8412 finalfinaltarget = waypoints[waypoint];
8413 finalpathfindpoint = -1;
8414 targetpathfindpoint = -1;
8415 lastpathfindpoint = -1;
8416 lastpathfindpoint2 = -1;
8417 lastpathfindpoint3 = -1;
8418 lastpathfindpoint4 = -1;
8420 //it's time to think (?)
8421 if (aiupdatedelay < 0 &&
8422 !Animation::animations[animTarget].attack &&
8423 animTarget != staggerbackhighanim &&
8424 animTarget != staggerbackhardanim &&
8425 animTarget != backhandspringanim &&
8426 animTarget != dodgebackanim) {
8428 if (weaponactive == -1 && num_weapons > 0) {
8429 drawkeydown = Random() % 2;
8433 rabbitkickenabled = Random() % 2;
8435 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
8436 XYZ targetpoint = Person::players[0]->coords;
8437 float vellength = findLength(&velocity);
8438 if (vellength != 0 &&
8439 distsq(&Person::players[0]->coords, &coords) < distsq(&rotatetarget, &coords)) {
8440 targetpoint += Person::players[0]->velocity *
8441 findDistance(&Person::players[0]->coords, &coords) / vellength;
8443 targetyaw = roughDirectionTo(coords, targetpoint);
8444 lookyaw = targetyaw;
8445 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
8447 if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1)) {
8449 } else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
8450 distsq(&coords, &Person::players[0]->coords) < 9) &&
8451 Person::players[0]->weaponactive != -1) {
8453 } else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0)) {
8458 //chill out around the corpse
8459 if (Person::players[0]->dead) {
8461 if (Random() % 10 == 0) {
8464 if (Random() % 100 == 0) {
8465 aitype = pathfindtype;
8466 finalfinaltarget = waypoints[waypoint];
8467 finalpathfindpoint = -1;
8468 targetpathfindpoint = -1;
8469 lastpathfindpoint = -1;
8470 lastpathfindpoint2 = -1;
8471 lastpathfindpoint3 = -1;
8472 lastpathfindpoint4 = -1;
8481 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8482 targetyaw += 90 * (whichdirection * 2 - 1);
8485 if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype) {
8490 if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7) {
8495 if (aitype != playercontrolled &&
8500 for (unsigned j = 0; j < Person::players.size(); j++) {
8501 if (j != id && !Person::players[j]->skeleton.free &&
8502 Person::players[j]->hasvictim &&
8503 (Tutorial::active && reversaltrain ||
8504 Random() % 2 == 0 && difficulty == 2 ||
8505 Random() % 4 == 0 && difficulty == 1 ||
8506 Random() % 8 == 0 && difficulty == 0 ||
8507 Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
8508 Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
8509 (Random() % 2 == 0 || difficulty == 2) ||
8510 (isIdle() || isRun()) &&
8511 Person::players[j]->weaponactive != -1 ||
8512 Person::players[j]->animTarget == swordslashanim &&
8513 weaponactive != -1 ||
8514 Person::players[j]->animTarget == staffhitanim ||
8515 Person::players[j]->animTarget == staffspinhitanim)) {
8516 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
8517 Person::players[j]->victim == Person::players[id] &&
8518 (Person::players[j]->animTarget == sweepanim ||
8519 Person::players[j]->animTarget == spinkickanim ||
8520 Person::players[j]->animTarget == staffhitanim ||
8521 Person::players[j]->animTarget == staffspinhitanim ||
8522 Person::players[j]->animTarget == winduppunchanim ||
8523 Person::players[j]->animTarget == upunchanim ||
8524 Person::players[j]->animTarget == wolfslapanim ||
8525 Person::players[j]->animTarget == knifeslashstartanim ||
8526 Person::players[j]->animTarget == swordslashanim &&
8527 (distsq(&Person::players[j]->coords, &coords) < 2 ||
8528 weaponactive != -1))) {
8538 Person::players[target]->Reverse();
8545 if (collided > .8 && jumppower >= 5 ||
8546 distsq(&coords, &Person::players[0]->coords) > 400 &&
8548 creature == rabbittype) {
8551 //TODO: why are we controlling the human?
8552 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
8553 Person::players[0]->jumpkeydown = 0;
8555 if (Person::players[0]->animTarget == jumpdownanim &&
8556 distsq(&Person::players[0]->coords, &coords) < 40) {
8563 if (Tutorial::active) {
8569 XYZ facing = coords;
8570 XYZ flatfacing = Person::players[0]->coords;
8571 facing.y += jointPos(head).y * scale;
8572 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
8573 if (occluded >= 2) {
8574 if (-1 != Object::checkcollide(facing, flatfacing)) {
8578 if (lastseentime <= 0 &&
8579 (creature != wolftype ||
8580 weaponstuck == -1)) {
8581 aitype = searchtype;
8583 lastseen = Person::players[0]->coords;
8592 if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
8593 (aitype == attacktypecutoff ||
8594 aitype == searchtype)) {
8595 if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
8596 XYZ test = Person::players[0]->coords;
8598 if (-1 == Object::checkcollide(Person::players[0]->coords, test)) {
8604 if (aitype == passivetype && !(numwaypoints > 1) ||
8606 pause && damage > superpermanentdamage) {
8625 XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0);
8626 facing = flatfacing;
8628 if (aitype == attacktypecutoff) {
8629 targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
8630 targetheadpitch = pitchTo(coords, Person::players[0]->coords);
8631 } else if (howactive >= typesleeping) {
8632 targetheadyaw = targetyaw;
8633 targetheadpitch = 0;
8635 if (interestdelay <= 0) {
8636 interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
8637 headtarget = coords;
8638 headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
8639 headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
8640 headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
8641 headtarget += facing * 1.5;
8643 targetheadyaw = 180 - roughDirectionTo(coords, headtarget);
8644 targetheadpitch = pitchTo(coords, headtarget);