2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2017 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
21 #include "Objects/Person.hpp"
23 #include "Animation/Animation.hpp"
24 #include "Audio/Sounds.hpp"
25 #include "Audio/openal_wrapper.hpp"
27 #include "Level/Awards.hpp"
28 #include "Level/Dialog.hpp"
29 #include "Tutorial.hpp"
30 #include "Utils/Folders.hpp"
32 extern float multiplier;
33 extern Terrain terrain;
35 extern int environment;
37 extern FRUSTUM frustum;
39 extern float realmultiplier;
41 extern float slomodelay;
42 extern bool cellophane;
43 extern float texdetail;
44 extern float realtexdetail;
45 extern int bloodtoggle;
46 extern bool autoslomo;
47 extern float camerashake;
49 extern float viewdistance;
50 extern float blackout;
51 extern int difficulty;
52 extern bool decalstoggle;
53 extern float fadestart;
55 extern bool winfreeze;
56 extern bool showpoints;
57 extern bool immediate;
58 extern float smoketex;
59 extern bool reversaltrain;
60 extern bool canattack;
62 extern float damagedealt;
64 extern float hostiletime;
66 extern bool gamestarted;
68 extern XYZ envsound[30];
69 extern float envsoundvol[30];
70 extern int numenvsounds;
71 extern float envsoundlife[30];
73 extern XYZ windvector;
75 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
76 std::vector<PersonType> PersonType::types;
78 PersonType::PersonType()
80 animTalkIdle = tempanim;
83 bool PersonType::hasAnimTalkIdle()
85 return (animTalkIdle != tempanim);
88 void PersonType::Load()
93 types[wolftype].proportions[0] = 1.1;
94 types[wolftype].proportions[1] = 1.1;
95 types[wolftype].proportions[2] = 1.1;
96 types[wolftype].proportions[3] = 1.1;
98 types[wolftype].animRun = wolfrunanim;
99 types[wolftype].animRunning = wolfrunninganim;
100 types[wolftype].animCrouch = wolfcrouchanim;
101 types[wolftype].animStop = wolfstopanim;
102 types[wolftype].animLanding = wolflandanim;
103 types[wolftype].animLandingHard = wolflandhardanim;
104 types[wolftype].animFightIdle = wolfidle;
105 types[wolftype].animBounceIdle = wolfidle;
107 types[wolftype].soundsAttack[0] = barksound;
108 types[wolftype].soundsAttack[1] = bark2sound;
109 types[wolftype].soundsAttack[2] = bark3sound;
110 types[wolftype].soundsAttack[3] = barkgrowlsound;
111 types[wolftype].soundsTalk[0] = growlsound;
112 types[wolftype].soundsTalk[1] = growl2sound;
114 types[wolftype].figureFileName = "Skeleton/BasicFigureWolf";
115 types[wolftype].lowFigureFileName = "Skeleton/BasicFigureWolfLow";
116 types[wolftype].clothesFileName = "Skeleton/RabbitBelt";
117 types[wolftype].modelFileNames[0] = "Models/Wolf.solid";
118 types[wolftype].modelFileNames[1] = "Models/Wolf2.solid";
119 types[wolftype].modelFileNames[2] = "Models/Wolf3.solid";
120 types[wolftype].modelFileNames[3] = "Models/Wolf4.solid";
121 types[wolftype].modelFileNames[4] = "Models/Wolf5.solid";
122 types[wolftype].modelFileNames[5] = "Models/Wolf6.solid";
123 types[wolftype].modelFileNames[6] = "Models/Wolf7.solid";
124 types[wolftype].lowModelFileName = "Models/WolfLow.solid";
125 types[wolftype].modelClothesFileName = "Models/Belt.solid";
127 types[wolftype].skins.resize(3);
128 types[wolftype].skins[0] = "Textures/Wolf.jpg";
129 types[wolftype].skins[1] = "Textures/DarkWolf.jpg";
130 types[wolftype].skins[2] = "Textures/SnowWolf.jpg";
133 types[rabbittype].proportions[0] = 1.2;
134 types[rabbittype].proportions[1] = 1.05;
135 types[rabbittype].proportions[2] = 1;
136 types[rabbittype].proportions[3] = 1.1;
137 types[rabbittype].proportions[3].y = 1.05;
139 types[rabbittype].animRun = runanim;
140 types[rabbittype].animRunning = rabbitrunninganim;
141 types[rabbittype].animCrouch = crouchanim;
142 types[rabbittype].animStop = stopanim;
143 types[rabbittype].animLanding = landanim;
144 types[rabbittype].animLandingHard = landhardanim;
145 types[rabbittype].animFightIdle = fightidleanim;
146 types[rabbittype].animBounceIdle = bounceidleanim;
148 types[rabbittype].soundsAttack[0] = rabbitattacksound;
149 types[rabbittype].soundsAttack[1] = rabbitattack2sound;
150 types[rabbittype].soundsAttack[2] = rabbitattack3sound;
151 types[rabbittype].soundsAttack[3] = rabbitattack4sound;
152 types[rabbittype].soundsTalk[0] = rabbitchitter;
153 types[rabbittype].soundsTalk[1] = rabbitchitter2;
155 types[rabbittype].figureFileName = "Skeleton/BasicFigure";
156 types[rabbittype].lowFigureFileName = "Skeleton/BasicFigureLow";
157 types[rabbittype].clothesFileName = "Skeleton/RabbitBelt";
158 types[rabbittype].modelFileNames[0] = "Models/Body.solid";
159 types[rabbittype].modelFileNames[1] = "Models/Body2.solid";
160 types[rabbittype].modelFileNames[2] = "Models/Body3.solid";
161 types[rabbittype].modelFileNames[3] = "Models/Body4.solid";
162 types[rabbittype].modelFileNames[4] = "Models/Body5.solid";
163 types[rabbittype].modelFileNames[5] = "Models/Body6.solid";
164 types[rabbittype].modelFileNames[6] = "Models/Body7.solid";
165 types[rabbittype].lowModelFileName = "Models/BodyLow.solid";
166 types[rabbittype].modelClothesFileName = "Models/Belt.solid";
168 types[rabbittype].skins.resize(10);
169 types[rabbittype].skins[0] = "Textures/Fur3.jpg";
170 types[rabbittype].skins[1] = "Textures/Fur.jpg";
171 types[rabbittype].skins[2] = "Textures/Fur2.jpg";
172 types[rabbittype].skins[3] = "Textures/Lynx.jpg";
173 types[rabbittype].skins[4] = "Textures/Otter.jpg";
174 types[rabbittype].skins[5] = "Textures/Opal.jpg";
175 types[rabbittype].skins[6] = "Textures/Sable.jpg";
176 types[rabbittype].skins[7] = "Textures/Chocolate.jpg";
177 types[rabbittype].skins[8] = "Textures/BW2.jpg";
178 types[rabbittype].skins[9] = "Textures/WB2.jpg";
184 , animCurrent(bounceidleanim)
185 , animTarget(bounceidleanim)
192 , howactive(typeactive)
194 , superruntoggle(false)
228 , rabbitkickenabled(false)
242 , superpermanentdamage(0)
285 , normalsupdatedelay(0)
289 , forwardkeydown(false)
290 , forwardstogglekeydown(false)
291 , rightkeydown(false)
295 , jumptogglekeydown(false)
296 , crouchkeydown(false)
297 , crouchtogglekeydown(false)
299 , drawtogglekeydown(false)
300 , throwkeydown(false)
301 , throwtogglekeydown(false)
302 , attackkeydown(false)
324 , whichdirection(false)
325 , whichdirectiondelay(0)
326 , avoidsomething(false)
336 , lefthandmorphness(0)
337 , righthandmorphness(0)
341 , targetlefthandmorphness(0)
342 , targetrighthandmorphness(0)
343 , targetheadmorphness(1)
344 , targetchestmorphness(0)
345 , targettailmorphness(0)
346 , lefthandmorphstart(0)
347 , lefthandmorphend(0)
348 , righthandmorphstart(0)
349 , righthandmorphend(0)
359 , highreversaldelay(0)
360 , lowreversaldelay(0)
409 , weaponstuckwhere(0)
422 , finalpathfindpoint(0)
423 , targetpathfindpoint(0)
424 , lastpathfindpoint(0)
425 , lastpathfindpoint2(0)
426 , lastpathfindpoint3(0)
427 , lastpathfindpoint4(0)
447 , neckspurtparticledelay(0)
452 , rabbitkickragdoll(false)
460 setProportions(1, 1, 1, 1);
463 /* Read a person in tfile. Throws an error if it’s not valid */
464 Person::Person(FILE* tfile, int mapvers, unsigned i)
468 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
470 funpackf(tfile, "Bi", &howactive);
472 howactive = typeactive;
475 funpackf(tfile, "Bf", &scale);
480 funpackf(tfile, "Bb", &immobile);
485 funpackf(tfile, "Bf", &yaw);
490 if (num_weapons < 0 || num_weapons > 5) {
491 throw InvalidPersonException();
493 if (num_weapons > 0 && num_weapons < 5) {
494 for (int j = 0; j < num_weapons; j++) {
495 weaponids[j] = weapons.size();
497 funpackf(tfile, "Bi", &type);
498 weapons.push_back(Weapon(type, id));
501 funpackf(tfile, "Bi", &numwaypoints);
502 for (int j = 0; j < numwaypoints; j++) {
503 funpackf(tfile, "Bf", &waypoints[j].x);
504 funpackf(tfile, "Bf", &waypoints[j].y);
505 funpackf(tfile, "Bf", &waypoints[j].z);
507 funpackf(tfile, "Bi", &waypointtype[j]);
509 waypointtype[j] = wpkeepwalking;
513 funpackf(tfile, "Bi", &waypoint);
514 if (waypoint > (numwaypoints - 1)) {
518 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
519 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
520 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
521 funpackf(tfile, "Bf Bf", &power, &speedmult);
524 funpackf(tfile, "Bf Bf Bf Bf", &proportions[0], &proportions[1], &proportions[2], &proportions[3]);
526 setProportions(1, 1, 1, 1);
529 funpackf(tfile, "Bi", &numclothes);
530 for (int k = 0; k < numclothes; k++) {
532 funpackf(tfile, "Bi", &templength);
533 for (int l = 0; l < templength; l++) {
534 funpackf(tfile, "Bb", &clothes[k][l]);
536 clothes[k][templength] = '\0';
537 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
543 if (creature == wolftype) {
545 damagetolerance = 300;
552 realoldcoords = coords;
555 void Person::skeletonLoad(bool clothes)
559 PersonType::types[creature].figureFileName,
560 PersonType::types[creature].lowFigureFileName,
561 PersonType::types[creature].clothesFileName,
562 PersonType::types[creature].modelFileNames[0],
563 PersonType::types[creature].modelFileNames[1],
564 PersonType::types[creature].modelFileNames[2],
565 PersonType::types[creature].modelFileNames[3],
566 PersonType::types[creature].modelFileNames[4],
567 PersonType::types[creature].modelFileNames[5],
568 PersonType::types[creature].modelFileNames[6],
569 PersonType::types[creature].lowModelFileName,
570 PersonType::types[creature].modelClothesFileName,
573 skeleton.drawmodel.textureptr.load(PersonType::types[creature].skins[whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
576 void Person::setProportions(float head, float body, float arms, float legs)
578 proportions[0] = head;
579 proportions[1] = body;
580 proportions[2] = arms;
581 proportions[3] = legs;
584 XYZ Person::getProportion(int part) const
586 XYZ prop = PersonType::types[creature].proportions[part] * proportions[part];
596 * GameTick/doPlayerCollisions
598 void Person::CheckKick()
600 if (!(hasvictim && (animTarget == rabbitkickanim && victim && victim != this->shared_from_this() && frameCurrent >= 2 && animCurrent == rabbitkickanim) && distsq(&coords, &victim->coords) < 1.2 && !victim->skeleton.free)) {
604 if (Animation::animations[victim->animTarget].height != lowheight) {
605 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
606 XYZ relative = velocity;
608 Normalise(&relative);
612 if (!Tutorial::active) {
613 emit_sound_at(heavyimpactsound, victim->coords);
616 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
617 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
620 victim->DoDamage(100 * damagemult / victim->protectionhigh);
627 animTarget = backflipanim;
629 velocity = facing * -10;
633 resume_stream(whooshsound);
636 award_bonus(id, cannon);
637 } else if (victim->isCrouch()) {
638 animTarget = rabbitkickreversedanim;
639 animCurrent = rabbitkickreversedanim;
640 victim->animCurrent = rabbitkickreversalanim;
641 victim->animTarget = rabbitkickreversalanim;
647 victim->oldcoords = victim->coords;
648 coords = victim->coords;
649 victim->targetyaw = targetyaw;
650 victim->victim = this->shared_from_this();
657 * GameTick::doPlayerCollisions - spread fire between players
658 * GameTick::ProcessDevKeys - press f to ignite
659 * Person::DoStuff - spread fire from lit campfires and bushes
661 void Person::CatchFire()
663 XYZ flatfacing, flatvelocity;
665 for (int i = 0; i < 10; i++) {
666 howmany = fabs(Random() % (skeleton.joints.size()));
668 flatvelocity = skeleton.joints[howmany].velocity;
669 flatfacing = skeleton.joints[howmany].position * scale + coords;
671 flatvelocity = velocity;
672 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
674 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
679 emit_sound_at(firestartsound, coords);
681 emit_stream_at(stream_firesound, coords);
689 * idle animation for this creature (depending on status)
691 int Person::getIdle()
693 if (Dialog::inDialog() && (howactive == typeactive) && PersonType::types[creature].hasAnimTalkIdle()) {
694 return PersonType::types[creature].animTalkIdle;
696 if (hasvictim && (victim != this->shared_from_this())) {
697 if ((!victim->dead && victim->aitype != passivetype &&
698 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
699 victim->id < Person::players.size())) {
700 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
701 return PersonType::types[creature].animFightIdle;
703 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
704 if (weapons[weaponids[weaponactive]].getType() == knife) {
705 return knifefightidleanim;
707 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1) {
708 return swordfightidlebothanim;
710 if (weapons[weaponids[weaponactive]].getType() == sword) {
711 return swordfightidleanim;
713 if (weapons[weaponids[weaponactive]].getType() == staff) {
714 return swordfightidleanim;
717 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause) {
718 return fightsidestep;
722 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype) {
725 if (howactive == typesitting) {
728 if (howactive == typesittingwall) {
731 if (howactive == typesleeping) {
734 if (howactive == typedead1) {
737 if (howactive == typedead2) {
740 if (howactive == typedead3) {
743 if (howactive == typedead4) {
746 return PersonType::types[creature].animBounceIdle;
750 * crouch animation for this creature
752 int Person::getCrouch()
754 return PersonType::types[creature].animCrouch;
758 * running animation for this creature (can be upright or all fours)
762 if (superruntoggle && (weaponactive == -1)) {
763 return PersonType::types[creature].animRunning;
765 return PersonType::types[creature].animRun;
771 int Person::getStop()
773 return PersonType::types[creature].animStop;
778 int Person::getLanding()
780 return PersonType::types[creature].animLanding;
785 int Person::getLandhard()
787 return PersonType::types[creature].animLandingHard;
793 * Person::DoAnimations
796 SolidHitBonus(int playerid)
798 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo) {
799 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
801 award_bonus(playerid, solidhit);
806 * spawns blood effects
808 void Person::DoBlood(float howmuch, int which)
810 // FIXME: should abstract out inputs
811 static int bleedxint, bleedyint;
813 if (bloodtoggle && !Tutorial::active) {
814 if (bleeding <= 0 && spurt) {
816 for (int i = 0; i < 3; i++) {
817 // emit blood particles
820 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
821 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
822 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
823 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
826 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
827 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
828 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
829 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
832 if (Random() % 2 == 0) { // 50% chance
833 for (int i = 0; i < 3; i++) {
834 if (Random() % 2 != 0) {
835 // emit teeth particles
838 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
839 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
842 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
843 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
847 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
849 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
851 Sprite::setLastSpriteSpecial(3); // sets it to teeth
857 // FIXME: manipulating attributes
858 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
861 while (PersonType::types[creature].bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || PersonType::types[creature].bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
862 bleedxint = abs(Random() % 512);
863 bleedyint = abs(Random() % 512);
867 bleedy /= realtexdetail;
868 bleedx /= realtexdetail;
869 direction = abs(Random() % 2) * 2 - 1;
878 * spawns big blood effects and ???
879 * modifies character's skin texture
881 void Person::DoBloodBig(float howmuch, int which)
883 static int bleedxint, bleedyint, i, j;
885 if (howmuch && id == 0) {
889 if (!Tutorial::active || id == 0) {
890 if (aitype != playercontrolled && howmuch > 0) {
894 if (creature == wolftype) {
895 int i = abs(Random() % 2);
897 whichsound = snarlsound;
900 whichsound = snarl2sound;
903 if (creature == rabbittype) {
904 int i = abs(Random() % 2);
906 whichsound = rabbitpainsound;
908 if (i == 1 && howmuch >= 2) {
909 whichsound = rabbitpain1sound;
913 if (whichsound != -1) {
914 emit_sound_at(whichsound, coords);
920 if (id == 0 && howmuch > 0) {
924 if (bloodtoggle && decalstoggle && !Tutorial::active) {
925 if (bleeding <= 0 && spurt) {
927 for (int i = 0; i < 3; i++) {
928 // emit blood particles
929 // FIXME: copypaste from above
932 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
933 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
934 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
935 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
938 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
939 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
940 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
941 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
946 // weird texture manipulation code follows.
947 // looks like this is painting blood onto the character's skin texture
948 // FIXME: surely there's a better way
950 int offsetx = 0, offsety = 0;
952 offsety = Random() % 40;
953 offsetx = abs(Random() % 60);
955 if (which == 190 || which == 185) {
956 offsety = Random() % 40;
957 offsetx = abs(Random() % 100) - 20;
960 offsety = Random() % 10;
961 offsetx = Random() % 10;
964 offsety = Random() % 20;
965 offsetx = Random() % 20;
967 if (which == 220 || which == 215) {
976 for (i = 0; i < 512; i++) {
977 for (j = 0; j < 512; j++) {
978 if (PersonType::types[creature].bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && PersonType::types[creature].bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1006 if (endx > 512 - 1) {
1009 if (endy > 512 - 1) {
1012 if (endx < startx) {
1015 if (endy < starty) {
1019 startx /= realtexdetail;
1020 starty /= realtexdetail;
1021 endx /= realtexdetail;
1022 endy /= realtexdetail;
1024 int texdetailint = realtexdetail;
1026 for (i = startx; i < endx; i++) {
1027 for (j = starty; j < endy; j++) {
1028 if (PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
1029 color = Random() % 85 + 170;
1030 where = i * skeleton.skinsize * 3 + j * 3;
1031 if (skeleton.skinText[where + 0] > color / 2) {
1032 skeleton.skinText[where + 0] = color / 2;
1034 skeleton.skinText[where + 1] = 0;
1035 skeleton.skinText[where + 2] = 0;
1039 skeleton.drawmodel.textureptr.bind();
1044 while (PersonType::types[creature].bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || PersonType::types[creature].bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
1045 bleedxint = abs(Random() % 512);
1046 bleedyint = abs(Random() % 512);
1048 bleedy = bleedxint + offsetx;
1049 bleedx = bleedyint + offsety;
1050 bleedy /= realtexdetail;
1051 bleedx /= realtexdetail;
1058 if (bleedx > skeleton.skinsize - 1) {
1059 bleedx = skeleton.skinsize - 1;
1061 if (bleedy > skeleton.skinsize - 1) {
1062 bleedy = skeleton.skinsize - 1;
1064 direction = abs(Random() % 2) * 2 - 1;
1066 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1067 deathbleeding += bleeding;
1068 bloodloss += bleeding * 3;
1070 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1071 if (abs(Random() % 2) == 0) {
1072 aitype = gethelptype;
1075 aitype = attacktypecutoff;
1085 * similar to DoBloodBig
1087 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
1090 static XYZ bloodvel;
1091 static XYZ startpoint, endpoint, colpoint, movepoint;
1092 static float rotationpoint;
1093 static int whichtri;
1094 static XYZ p1, p2, p3, p0;
1097 float coordsx, coordsy;
1100 if (bloodtoggle && decalstoggle && !Tutorial::active) {
1102 if (!skeleton.free) {
1103 where = DoRotation(where, 0, -yaw, 0);
1107 startpoint.y += 100;
1112 // ray testing for a tri in the character model
1113 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
1114 if (whichtri != -1) {
1115 // low level geometry math
1117 p1 = skeleton.drawmodel.getTriangleVertex(whichtri, 0);
1118 p2 = skeleton.drawmodel.getTriangleVertex(whichtri, 1);
1119 p3 = skeleton.drawmodel.getTriangleVertex(whichtri, 2);
1121 bary.x = distsq(&p0, &p1);
1122 bary.y = distsq(&p0, &p2);
1123 bary.z = distsq(&p0, &p3);
1125 total = bary.x + bary.y + bary.z;
1130 bary.x = 1 - bary.x;
1131 bary.y = 1 - bary.y;
1132 bary.z = 1 - bary.z;
1134 total = bary.x + bary.y + bary.z;
1139 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1140 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1141 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1142 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1143 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1144 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1145 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;
1146 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;
1148 if (bleeding <= 0 && spurt) {
1150 for (int i = 0; i < 3; i++) {
1151 // emit blood particles
1152 // FIXME: more copypaste code
1154 if (skeleton.free) {
1155 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1156 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1157 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1158 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1161 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1162 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1163 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1164 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1169 // texture manipulation follows
1171 int offsetx = 0, offsety = 0;
1172 offsetx = (1 + coordsy) * 512 - 291;
1173 offsety = coordsx * 512 - 437;
1180 for (i = 0; i < 512; i++) {
1181 for (j = 0; j < 512; j++) {
1182 if (PersonType::types[creature].bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && PersonType::types[creature].bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1209 if (endx > 512 - 1) {
1212 if (endy > 512 - 1) {
1215 if (endx < startx) {
1218 if (endy < starty) {
1222 startx /= realtexdetail;
1223 starty /= realtexdetail;
1224 endx /= realtexdetail;
1225 endy /= realtexdetail;
1227 int texdetailint = realtexdetail;
1229 for (i = startx; i < endx; i++) {
1230 for (j = starty; j < endy; j++) {
1231 if (PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
1232 color = Random() % 85 + 170;
1233 where = i * skeleton.skinsize * 3 + j * 3;
1234 if (skeleton.skinText[where + 0] > color / 2) {
1235 skeleton.skinText[where + 0] = color / 2;
1237 skeleton.skinText[where + 1] = 0;
1238 skeleton.skinText[where + 2] = 0;
1239 } else if (PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= 160 + 4 && PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= 160 - 4) {
1240 color = Random() % 85 + 170;
1241 where = i * skeleton.skinsize * 3 + j * 3;
1242 if (skeleton.skinText[where + 0] > color / 2) {
1243 skeleton.skinText[where + 0] = color / 2;
1245 skeleton.skinText[where + 1] = 0;
1246 skeleton.skinText[where + 2] = 0;
1250 skeleton.drawmodel.textureptr.bind();
1253 bleedy = (1 + coordsy) * 512;
1254 bleedx = coordsx * 512;
1255 bleedy /= realtexdetail;
1256 bleedx /= realtexdetail;
1263 if (bleedx > skeleton.skinsize - 1) {
1264 bleedx = skeleton.skinsize - 1;
1266 if (bleedy > skeleton.skinsize - 1) {
1267 bleedy = skeleton.skinsize - 1;
1269 direction = abs(Random() % 2) * 2 - 1;
1271 if (whichtri == -1) {
1275 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1276 deathbleeding += bleeding;
1277 bloodloss += bleeding * 3;
1279 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1280 if (abs(Random() % 2) == 0) {
1281 aitype = gethelptype;
1284 aitype = attacktypecutoff;
1295 * guessing this performs a reversal
1297 void Person::Reverse()
1299 if (!((victim->aitype == playercontrolled || hostiletime > 1 || staggerdelay <= 0) && victim->animTarget != jumpupanim && victim->animTarget != jumpdownanim && (!Tutorial::active || cananger) && hostile)) {
1303 if (normaldotproduct(victim->facing, victim->coords - coords) > 0 && (victim->id != 0 || difficulty >= 2) && (creature != wolftype || victim->creature == wolftype)) {
1307 if (animTarget == sweepanim) {
1308 animTarget = sweepreversedanim;
1309 animCurrent = sweepreversedanim;
1310 victim->animCurrent = sweepreversalanim;
1311 victim->animTarget = sweepreversalanim;
1313 if (animTarget == spinkickanim) {
1314 animTarget = spinkickreversedanim;
1315 animCurrent = spinkickreversedanim;
1316 victim->animCurrent = spinkickreversalanim;
1317 victim->animTarget = spinkickreversalanim;
1319 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1320 if (animTarget == rabbittacklinganim) {
1323 victim->frameCurrent = 6;
1324 victim->frameTarget = 7;
1326 animTarget = upunchreversedanim;
1327 animCurrent = upunchreversedanim;
1328 victim->animCurrent = upunchreversalanim;
1329 victim->animTarget = upunchreversalanim;
1331 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1332 if (victim->weaponactive != -1) {
1333 victim->throwtogglekeydown = 1;
1334 XYZ tempVelocity = victim->velocity * .2;
1335 if (tempVelocity.x == 0) {
1336 tempVelocity.x = .1;
1338 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1339 victim->num_weapons--;
1340 if (victim->num_weapons) {
1341 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1342 if (victim->weaponstuck == victim->num_weapons) {
1343 victim->weaponstuck = 0;
1347 victim->weaponactive = -1;
1348 for (unsigned j = 0; j < Person::players.size(); j++) {
1349 Person::players[j]->wentforweapon = 0;
1353 animTarget = staffhitreversedanim;
1354 animCurrent = staffhitreversedanim;
1355 victim->animCurrent = staffhitreversalanim;
1356 victim->animTarget = staffhitreversalanim;
1358 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1359 if (victim->weaponactive != -1) {
1360 victim->throwtogglekeydown = 1;
1361 XYZ tempVelocity = victim->velocity * .2;
1362 if (tempVelocity.x == 0) {
1363 tempVelocity.x = .1;
1365 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1366 victim->num_weapons--;
1367 if (victim->num_weapons) {
1368 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1369 if (victim->weaponstuck == victim->num_weapons) {
1370 victim->weaponstuck = 0;
1374 victim->weaponactive = -1;
1375 for (unsigned j = 0; j < Person::players.size(); j++) {
1376 Person::players[j]->wentforweapon = 0;
1379 animTarget = staffspinhitreversedanim;
1380 animCurrent = staffspinhitreversedanim;
1381 victim->animCurrent = staffspinhitreversalanim;
1382 victim->animTarget = staffspinhitreversalanim;
1384 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1385 if (victim->weaponactive != -1) {
1386 victim->throwtogglekeydown = 1;
1387 XYZ tempVelocity = victim->velocity * .2;
1388 if (tempVelocity.x == 0) {
1389 tempVelocity.x = .1;
1391 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1392 victim->num_weapons--;
1393 if (victim->num_weapons) {
1394 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1395 if (victim->weaponstuck == victim->num_weapons) {
1396 victim->weaponstuck = 0;
1400 victim->weaponactive = -1;
1401 for (unsigned j = 0; j < Person::players.size(); j++) {
1402 Person::players[j]->wentforweapon = 0;
1405 animTarget = swordslashreversedanim;
1406 animCurrent = swordslashreversedanim;
1407 victim->animCurrent = swordslashreversalanim;
1408 victim->animTarget = swordslashreversalanim;
1410 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1411 if (victim->weaponactive != -1) {
1412 victim->throwtogglekeydown = 1;
1413 XYZ tempVelocity = victim->velocity * .2;
1414 if (tempVelocity.x == 0) {
1415 tempVelocity.x = .1;
1417 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1418 victim->num_weapons--;
1419 if (victim->num_weapons) {
1420 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1421 if (victim->weaponstuck == victim->num_weapons) {
1422 victim->weaponstuck = 0;
1426 victim->weaponactive = -1;
1427 for (unsigned j = 0; j < Person::players.size(); j++) {
1428 Person::players[j]->wentforweapon = 0;
1431 animTarget = knifeslashreversedanim;
1432 animCurrent = knifeslashreversedanim;
1433 victim->animCurrent = knifeslashreversalanim;
1434 victim->animTarget = knifeslashreversalanim;
1436 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1437 victim->targettilt2 = targettilt2;
1438 victim->frameCurrent = frameCurrent;
1439 victim->frameTarget = frameTarget;
1440 victim->target = target;
1441 victim->velocity = 0;
1442 victim->oldcoords = victim->coords;
1443 victim->coords = coords;
1444 victim->targetyaw = targetyaw;
1445 victim->yaw = targetyaw;
1446 victim->victim = this->shared_from_this();
1448 if (animTarget == winduppunchanim) {
1449 animTarget = winduppunchblockedanim;
1450 victim->animTarget = blockhighleftanim;
1451 victim->frameTarget = 1;
1452 victim->target = .5;
1453 victim->victim = this->shared_from_this();
1454 victim->targetyaw = targetyaw + 180;
1456 if (animTarget == wolfslapanim) {
1457 animTarget = winduppunchblockedanim;
1458 victim->animTarget = blockhighleftanim;
1459 victim->frameTarget = 1;
1460 victim->target = .5;
1461 victim->victim = this->shared_from_this();
1462 victim->targetyaw = targetyaw + 180;
1464 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1465 animTarget = swordslashparriedanim;
1466 parriedrecently = .4;
1467 victim->parriedrecently = 0;
1468 victim->animTarget = swordslashparryanim;
1469 victim->frameTarget = 1;
1470 victim->target = .5;
1471 victim->victim = this->shared_from_this();
1472 victim->targetyaw = targetyaw + 180;
1474 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1475 if (victim->weaponactive != -1) {
1476 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1477 if (weapons[victim->weaponids[0]].getType() == staff) {
1478 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1480 if (weapons[weaponids[0]].getType() == staff) {
1481 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1483 emit_sound_at(swordstaffsound, victim->coords);
1485 emit_sound_at(metalhitsound, victim->coords);
1489 victim->Puff(righthand);
1491 victim->frameTarget = 0;
1492 victim->animTarget = staggerbackhighanim;
1493 victim->targetyaw = targetyaw + 180;
1495 aim = DoRotation(facing, 0, 90, 0) * 21;
1497 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1498 victim->num_weapons--;
1499 if (victim->num_weapons) {
1500 victim->weaponids[0] = victim->weaponids[num_weapons];
1501 if (victim->weaponstuck == victim->num_weapons) {
1502 victim->weaponstuck = 0;
1505 victim->weaponactive = -1;
1506 for (unsigned i = 0; i < Person::players.size(); i++) {
1507 Person::players[i]->wentforweapon = 0;
1511 if (abs(Random() % 20) == 0) {
1512 if (weaponactive != -1) {
1513 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1514 if (weapons[victim->weaponids[0]].getType() == staff) {
1515 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1517 if (weapons[weaponids[0]].getType() == staff) {
1518 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1521 emit_sound_at(swordstaffsound, coords);
1523 emit_sound_at(metalhitsound, coords);
1531 animTarget = staggerbackhighanim;
1532 targetyaw = targetyaw + 180;
1534 aim = DoRotation(facing, 0, 90, 0) * 21;
1536 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1539 weaponids[0] = weaponids[num_weapons];
1540 if (weaponstuck == num_weapons) {
1545 for (unsigned i = 0; i < Person::players.size(); i++) {
1546 Person::players[i]->wentforweapon = 0;
1551 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1552 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1553 victim->animTarget = dodgebackanim;
1554 victim->frameTarget = 0;
1558 rotatetarget = coords - victim->coords;
1559 Normalise(&rotatetarget);
1560 victim->targetyaw = -asin(0 - rotatetarget.x);
1561 victim->targetyaw *= 360 / 6.28;
1562 if (rotatetarget.z < 0) {
1563 victim->targetyaw = 180 - victim->targetyaw;
1566 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1568 victim->lastattack3 = victim->lastattack2;
1569 victim->lastattack2 = victim->lastattack;
1570 victim->lastattack = victim->animTarget;
1572 victim->animTarget = sweepanim;
1573 victim->frameTarget = 0;
1577 rotatetarget = coords - victim->coords;
1578 Normalise(&rotatetarget);
1579 victim->targetyaw = -asin(0 - rotatetarget.x);
1580 victim->targetyaw *= 360 / 6.28;
1581 if (rotatetarget.z < 0) {
1582 victim->targetyaw = 180 - victim->targetyaw;
1585 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1587 victim->lastattack3 = victim->lastattack2;
1588 victim->lastattack2 = victim->lastattack;
1589 victim->lastattack = victim->animTarget;
1595 victim->velocity = 0;
1597 if (aitype != playercontrolled) {
1599 if (escapednum < 2) {
1600 int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
1601 if ((Random() % chances) == 0) {
1607 if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal) {
1615 void Person::DoDamage(float howmuch)
1619 damagetaken += howmuch / power;
1621 damagedealt += howmuch / power;
1625 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo)) {
1630 if (!Tutorial::active) {
1631 damage += howmuch / power;
1632 permanentdamage += howmuch / 2 / power;
1633 superpermanentdamage += howmuch / 4 / power;
1636 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2) {
1639 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt) {
1644 camerashake += howmuch / 100;
1645 if ((howmuch > 50 && damage > damagetolerance / 2)) {
1646 blackout = damage / damagetolerance;
1654 if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile)) {
1655 aitype = attacktypecutoff;
1657 if (!Tutorial::active && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1658 if (abs(Random() % 2) == 0) {
1659 aitype = gethelptype;
1662 aitype = attacktypecutoff;
1667 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1670 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1671 if (skeleton.free) {
1672 flatvelocity2 = skeleton.joints[i].velocity;
1673 flatfacing2 = skeleton.joints[i].position * scale + coords;
1675 flatvelocity2 = velocity;
1676 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1678 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1679 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1680 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1681 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1682 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1683 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1686 emit_sound_at(splattersound, coords);
1691 if (!dead && creature == wolftype) {
1692 award_bonus(0, Wolfbonus);
1699 if (!Tutorial::active || id == 0) {
1700 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1701 int whichsound = -1;
1703 if (creature == wolftype) {
1704 int i = abs(Random() % 2);
1706 whichsound = snarlsound;
1709 whichsound = snarl2sound;
1712 if (creature == rabbittype) {
1713 int i = abs(Random() % 2);
1715 whichsound = rabbitpainsound;
1717 if (i == 1 && damage > damagetolerance) {
1718 whichsound = rabbitpain1sound;
1722 if (whichsound != -1) {
1723 emit_sound_at(whichsound, coords);
1724 addEnvSound(coords);
1732 * calculate/animate head facing direction?
1734 void Person::DoHead()
1736 static XYZ rotatearound;
1738 static float lookspeed = 500;
1740 if (!freeze && !winfreeze) {
1743 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1744 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1746 while (targetheadyaw > 180) {
1747 targetheadyaw -= 360;
1749 while (targetheadyaw < -180) {
1750 targetheadyaw += 360;
1753 if (targetheadyaw > 160) {
1754 targetheadpitch = targetheadpitch * -1;
1756 if (targetheadyaw < -160) {
1757 targetheadpitch = targetheadpitch * -1;
1759 if (targetheadyaw > 160) {
1760 targetheadyaw = targetheadyaw - 180;
1762 if (targetheadyaw < -160) {
1763 targetheadyaw = targetheadyaw + 180;
1766 if (targetheadpitch > 120) {
1767 targetheadpitch = 120;
1769 if (targetheadpitch < -120) {
1770 targetheadpitch = -120;
1772 if (targetheadyaw > 120) {
1773 targetheadyaw = 120;
1775 if (targetheadyaw < -120) {
1776 targetheadyaw = -120;
1780 targetheadpitch = 0;
1783 if (targetheadyaw > 80) {
1786 if (targetheadyaw < -80) {
1787 targetheadyaw = -80;
1789 if (targetheadpitch > 50) {
1790 targetheadpitch = 50;
1792 if (targetheadpitch < -50) {
1793 targetheadpitch = -50;
1797 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed) {
1798 headyaw = targetheadyaw;
1799 } else if (headyaw > targetheadyaw) {
1800 headyaw -= multiplier * lookspeed;
1801 } else if (headyaw < targetheadyaw) {
1802 headyaw += multiplier * lookspeed;
1805 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2) {
1806 headpitch = targetheadpitch;
1807 } else if (headpitch > targetheadpitch) {
1808 headpitch -= multiplier * lookspeed / 2;
1809 } else if (headpitch < targetheadpitch) {
1810 headpitch += multiplier * lookspeed / 2;
1813 rotatearound = jointPos(neck);
1814 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1818 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1819 facing = DoRotation(facing, headpitch * .4, 0, 0);
1820 facing = DoRotation(facing, 0, headyaw * .4, 0);
1823 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1824 facing = DoRotation(facing, headpitch * .8, 0, 0);
1825 facing = DoRotation(facing, 0, headyaw * .8, 0);
1828 if (animTarget == walkanim) {
1829 facing = DoRotation(facing, headpitch * .6, 0, 0);
1830 facing = DoRotation(facing, 0, headyaw * .6, 0);
1833 skeleton.specialforward[0] = facing;
1834 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1835 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
1836 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1837 skeleton.FindRotationMuscle(i, animTarget);
1844 * ragdolls character?
1846 void Person::RagDoll(bool checkcollision)
1851 if (!skeleton.free) {
1855 if (id == 0 && isFlip()) {
1863 facing = DoRotation(facing, 0, yaw, 0);
1865 skeleton.freetime = 0;
1867 skeleton.longdead = 0;
1870 skeleton.broken = 0;
1871 skeleton.spinny = 1;
1873 skeleton.freefall = 1;
1875 if (!isnormal(velocity.x)) {
1878 if (!isnormal(velocity.y)) {
1881 if (!isnormal(velocity.z)) {
1884 if (!isnormal(yaw)) {
1887 if (!isnormal(coords.x)) {
1890 if (!isnormal(tilt)) {
1893 if (!isnormal(tilt2)) {
1897 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1898 skeleton.joints[i].delay = 0;
1899 skeleton.joints[i].locked = 0;
1900 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1901 if (!isnormal(skeleton.joints[i].position.x)) {
1902 skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1904 if (!isnormal(skeleton.joints[i].position.x)) {
1905 skeleton.joints[i].position = coords;
1907 skeleton.joints[i].position.y += .1;
1908 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1909 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1912 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1913 skeleton.joints[i].velocity = 0;
1914 skeleton.joints[i].velchange = 0;
1916 skeleton.DoConstraints(&coords, &scale);
1917 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
1918 skeleton.DoConstraints(&coords, &scale);
1919 skeleton.DoConstraints(&coords, &scale);
1920 skeleton.DoConstraints(&coords, &scale);
1921 skeleton.DoConstraints(&coords, &scale);
1924 speed = targetFrame().speed * 2;
1925 if (currentFrame().speed > targetFrame().speed) {
1926 speed = currentFrame().speed * 2;
1929 speed = transspeed * 2;
1934 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1935 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height) {
1936 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);
1938 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1940 change.x = (float)(Random() % 100) / 100;
1941 change.y = (float)(Random() % 100) / 100;
1942 change.z = (float)(Random() % 100) / 100;
1943 skeleton.joints[i].velocity += change;
1944 skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change;
1946 change.x = (float)(Random() % 100) / 100;
1947 change.y = (float)(Random() % 100) / 100;
1948 change.z = (float)(Random() % 100) / 100;
1949 skeleton.joints[i].velchange += change;
1950 skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change;
1953 if (checkcollision) {
1956 if (!skeleton.joints.empty()) {
1959 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1960 average += skeleton.joints[j].position;
1962 average /= skeleton.joints.size();
1963 coords += average * scale;
1964 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1965 skeleton.joints[j].position -= average;
1969 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1970 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1971 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
1972 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1975 if (SphereCheck(&lowpoint, 3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
1976 coords.x = lowpoint.x;
1977 coords.z = lowpoint.z;
1986 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1987 velocity += skeleton.joints[i].velocity * scale;
1989 velocity /= skeleton.joints.size();
1992 if (Random() % 2 == 0) {
1993 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1994 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1995 weapons[weaponids[0]].velocity.x += .01;
1998 weaponids[0] = weaponids[num_weapons];
1999 if (weaponstuck == num_weapons) {
2004 for (unsigned i = 0; i < Person::players.size(); i++) {
2005 Person::players[i]->wentforweapon = 0;
2010 animTarget = bounceidleanim;
2011 animCurrent = bounceidleanim;
2019 void Person::FootLand(bodypart whichfoot, float opacity)
2021 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
2022 cerr << "FootLand called on wrong bodypart" << endl;
2025 static XYZ terrainlight;
2026 static XYZ footvel, footpoint;
2027 if (opacity >= 1 || skiddelay <= 0) {
2030 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2031 if (distsq(&footpoint, &viewer)) {
2032 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
2034 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
2035 footvel = velocity / 5;
2036 if (footvel.y < .8) {
2039 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2040 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
2041 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
2042 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
2043 if (environment == snowyenvironment) {
2044 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
2046 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
2048 } else if (environment == grassyenvironment) {
2049 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
2050 } else if (environment == desertenvironment) {
2051 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
2053 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
2057 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
2058 footvel = velocity / 5;
2059 if (footvel.y < .8) {
2062 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2063 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
2064 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
2071 * make a puff effect at a body part (dust effect?)
2073 void Person::Puff(int whichlabel)
2075 static XYZ footvel, footpoint;
2078 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
2079 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
2083 * I think I added this in an attempt to clean up code
2085 void Person::setTargetAnimation(int animation)
2087 animTarget = animation;
2096 void Person::DoAnimations()
2098 if (!skeleton.free) {
2099 static float oldtarget;
2101 if (isIdle() && animCurrent != getIdle()) {
2102 normalsupdatedelay = 0;
2105 if (animTarget == tempanim || animCurrent == tempanim) {
2106 Animation::animations[tempanim] = tempanimation;
2108 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
2115 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
2116 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
2118 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z)) {
2121 if (!crouchkeydown && velocity.y >= -15) {
2125 if ((animCurrent == jumpupanim || animTarget == jumpdownanim) /*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
2130 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
2132 if (normaldotproduct(targfacing, velocity) >= -.3) {
2133 animTarget = flipanim;
2135 animTarget = backflipanim;
2137 crouchtogglekeydown = 1;
2146 if (Animation::animations[animTarget].attack != reversed) {
2149 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
2150 crouchtogglekeydown = 0;
2151 if (aitype == playercontrolled) {
2155 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain)) {
2159 crouchtogglekeydown = 1;
2163 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
2165 normalsupdatedelay = 0;
2170 if (animTarget == rollanim && frameTarget == 3 && onfire) {
2172 emit_sound_at(fireendsound, coords);
2173 pause_sound(stream_firesound);
2177 if (animTarget == rabbittacklinganim && frameTarget == 1) {
2178 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0) {
2181 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
2182 if (normaldotproduct(victim->facing, facing) > 0) {
2183 victim->animTarget = rabbittackledbackanim;
2185 victim->animTarget = rabbittackledfrontanim;
2187 victim->frameTarget = 2;
2190 victim->targetyaw = yaw;
2191 if (victim->aitype == gethelptype) {
2192 victim->DoDamage(victim->damagetolerance - victim->damage);
2194 //victim->DoDamage(30);
2195 if (creature == wolftype) {
2197 emit_sound_at(clawslicesound, victim->coords);
2199 victim->DoBloodBig(1 / victim->armorhead, 210);
2201 award_bonus(id, TackleBonus,
2202 victim->aitype == gethelptype ? 50 : 0);
2206 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2207 if (weapons[weaponids[0]].getType() == knife) {
2208 if (weaponactive == -1) {
2210 } else if (weaponactive == 0) {
2214 if (weaponactive == -1) {
2215 emit_sound_at(knifesheathesound, coords);
2217 if (weaponactive != -1) {
2218 emit_sound_at(knifedrawsound, coords, 128);
2221 drawtogglekeydown = 1;
2224 if (!Tutorial::active || id == 0) {
2225 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2226 int whichsound = -1;
2228 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2229 if (targetFrame().label == 1) {
2230 whichsound = footstepsound;
2232 whichsound = footstepsound2;
2234 if (targetFrame().label == 1) {
2235 FootLand(leftfoot, 1);
2237 if (targetFrame().label == 2) {
2238 FootLand(rightfoot, 1);
2240 if (targetFrame().label == 3 && isRun()) {
2241 FootLand(rightfoot, 1);
2242 FootLand(leftfoot, 1);
2245 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2246 if (targetFrame().label == 1) {
2247 whichsound = footstepsound3;
2249 whichsound = footstepsound4;
2254 if (targetFrame().label == 1) {
2255 whichsound = footstepsound3;
2257 whichsound = footstepsound4;
2260 if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2261 if (Animation::animations[animTarget].attack != neutral) {
2262 unsigned r = abs(Random() % 3);
2264 whichsound = lowwhooshsound;
2267 whichsound = midwhooshsound;
2270 whichsound = highwhooshsound;
2273 if (Animation::animations[animTarget].attack == neutral) {
2274 whichsound = movewhooshsound;
2276 } else if (targetFrame().label == 4) {
2277 whichsound = knifeswishsound;
2279 if (targetFrame().label == 8 && !Tutorial::active) {
2280 whichsound = landsound2;
2283 if (whichsound != -1) {
2284 emit_sound_at(whichsound, coords, 256.);
2287 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2288 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2289 addEnvSound(coords, 15);
2291 addEnvSound(coords, 6);
2296 if (targetFrame().label == 3) {
2298 emit_sound_at(whichsound, coords, 128.);
2305 if (!Tutorial::active || id == 0) {
2306 if (speechdelay <= 0) {
2307 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
2308 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2309 int whichsound = -1;
2310 if (targetFrame().label == 4 && aitype != playercontrolled) {
2311 if (Animation::animations[animTarget].attack != neutral) {
2312 unsigned r = abs(Random() % 4);
2313 whichsound = PersonType::types[creature].soundsAttack[r];
2318 if (whichsound != -1) {
2319 emit_sound_at(whichsound, coords);
2326 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2327 FootLand(leftfoot, 1);
2328 FootLand(rightfoot, 1);
2332 currentoffset = targetoffset;
2333 frameTarget = frameCurrent;
2334 animCurrent = animTarget;
2337 if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2338 for (unsigned i = 0; i < weapons.size(); i++) {
2339 if (weapons[i].owner == -1) {
2340 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2341 if (distsq(&coords, &weapons[i].position) >= 1) {
2342 if (weapons[i].getType() != staff) {
2343 emit_sound_at(knifedrawsound, coords, 128.);
2353 if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2354 for (unsigned i = 0; i < weapons.size(); i++) {
2355 bool willwork = true;
2356 if (weapons[i].owner != -1) {
2357 if (Person::players[weapons[i].owner]->weaponstuck != -1) {
2358 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i)) {
2359 if (Person::players[weapons[i].owner]->num_weapons > 1) {
2365 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free)) {
2366 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2367 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2368 bool fleshstuck = false;
2369 if (weapons[i].owner != -1) {
2370 if (victim->weaponstuck != -1) {
2371 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2377 emit_sound_at(fleshstabremovesound, coords, 128.);
2379 if (weapons[i].getType() != staff) {
2380 emit_sound_at(knifedrawsound, coords, 128.);
2383 if (weapons[i].owner != -1) {
2384 victim = Person::players[weapons[i].owner];
2385 if (victim->num_weapons == 1) {
2386 victim->num_weapons = 0;
2388 victim->num_weapons = 1;
2391 //victim->weaponactive=-1;
2392 victim->skeleton.longdead = 0;
2393 victim->skeleton.free = 1;
2394 victim->skeleton.broken = 0;
2396 for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) {
2397 victim->skeleton.joints[j].velchange = 0;
2398 victim->skeleton.joints[j].locked = 0;
2404 Normalise(&relative);
2405 XYZ footvel, footpoint;
2407 footpoint = weapons[i].position;
2408 if (victim->weaponstuck != -1) {
2409 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2411 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2413 weapons[i].bloody = 2;
2414 weapons[i].blooddrip = 5;
2415 victim->weaponstuck = -1;
2418 if (victim->num_weapons > 0) {
2419 if (victim->weaponstuck != 0 && victim->weaponstuck != -1) {
2420 victim->weaponstuck = 0;
2422 if (victim->weaponids[0] == int(i)) {
2423 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2427 victim->jointVel(abdomen) += relative * 6;
2428 victim->jointVel(neck) += relative * 6;
2429 victim->jointVel(rightshoulder) += relative * 6;
2430 victim->jointVel(leftshoulder) += relative * 6;
2439 if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2440 if (weaponactive == -1) {
2442 } else if (weaponactive == 0) {
2444 if (num_weapons == 2) {
2446 buffer = weaponids[0];
2447 weaponids[0] = weaponids[1];
2448 weaponids[1] = buffer;
2451 if (weaponactive == -1) {
2452 emit_sound_at(knifesheathesound, coords, 128.);
2454 if (weaponactive != -1) {
2455 emit_sound_at(knifedrawsound, coords, 128.);
2459 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2460 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2461 Normalise(&rotatetarget);
2462 targetyaw = -asin(0 - rotatetarget.x);
2463 targetyaw *= 360 / 6.28;
2464 if (rotatetarget.z < 0) {
2465 targetyaw = 180 - targetyaw;
2468 if (animTarget == walljumprightkickanim) {
2471 if (animTarget == walljumpleftkickanim) {
2478 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0)) {
2482 if (distsq(&victim->coords, &/*Person::players[i]->*/ coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1) {
2490 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2491 animTarget = rabbittackleanim;
2493 emit_sound_at(jumpsound, coords);
2501 targetloc = velocity;
2502 Normalise(&targetloc);
2503 targetloc += coords;
2504 for (unsigned i = 0; i < Person::players.size(); i++) {
2506 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2507 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2512 if (closestid != -1) {
2513 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2515 victim = Person::players[closestid];
2516 coords = victim->coords;
2517 animCurrent = rabbittacklinganim;
2518 animTarget = rabbittacklinganim;
2522 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2523 rotatetarget = coords - victim->coords;
2524 Normalise(&rotatetarget);
2525 targetyaw = -asin(0 - rotatetarget.x);
2526 targetyaw *= 360 / 6.28;
2527 if (rotatetarget.z < 0) {
2528 targetyaw = 180 - targetyaw;
2531 if (animTarget != rabbitrunninganim) {
2532 emit_sound_at(jumpsound, coords, 128.);
2539 float damagemult = 1 * power;
2540 if (creature == wolftype) {
2541 damagemult = 2.5 * power;
2544 damagemult /= victim->damagetolerance / 200;
2546 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)) {
2547 if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2548 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2553 if (Random() % 2 || creature == wolftype) {
2556 if (creature == wolftype) {
2560 if (!Tutorial::active) {
2561 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2563 if (creature == wolftype) {
2564 emit_sound_at(clawslicesound, victim->coords, 128.);
2566 victim->DoBloodBig(2 / victim->armorhead, 175);
2570 relative = victim->coords - coords;
2572 Normalise(&relative);
2573 relative = DoRotation(relative, 0, -90, 0);
2574 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2575 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2577 victim->jointVel(head) += relative * damagemult * 200;
2579 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2585 if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2586 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2591 if (Random() % 2 || creature == wolftype) {
2593 if (creature == wolftype) {
2597 emit_sound_at(whooshhitsound, victim->coords);
2598 if (creature == wolftype) {
2599 emit_sound_at(clawslicesound, victim->coords, 128.);
2601 victim->DoBloodBig(2, 175);
2605 relative = victim->coords - coords;
2607 Normalise(&relative);
2609 Normalise(&relative);
2610 relative = DoRotation(relative, 0, 90, 0);
2611 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2612 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2614 victim->jointVel(head) += relative * damagemult * 100;
2616 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2620 if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2621 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2628 if (!Tutorial::active) {
2629 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2631 if (creature == wolftype) {
2632 emit_sound_at(clawslicesound, victim->coords, 128.);
2634 victim->DoBloodBig(2 / victim->armorhead, 175);
2640 Normalise(&relative);
2641 relative = DoRotation(relative, 0, -90, 0);
2642 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2643 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2645 victim->jointVel(head) += relative * damagemult * 200;
2647 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2649 if (victim->damage > victim->damagetolerance) {
2650 award_bonus(id, style);
2657 if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2658 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2665 if (!Tutorial::active) {
2666 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2668 if (creature == wolftype) {
2669 emit_sound_at(clawslicesound, victim->coords, 128.);
2671 victim->DoBloodBig(2 / victim->armorhead, 175);
2677 Normalise(&relative);
2678 relative = DoRotation(relative, 0, 90, 0);
2679 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2680 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2682 victim->jointVel(head) += relative * damagemult * 200;
2684 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2686 if (victim->damage > victim->damagetolerance) {
2687 award_bonus(id, style);
2694 if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2695 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2704 emit_sound_at(whooshhitsound, victim->coords);
2707 relative = victim->coords - coords;
2709 Normalise(&relative);
2710 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2711 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2713 victim->jointVel(head) += relative * damagemult * 100;
2715 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2719 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
2720 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2725 emit_sound_at(whooshhitsound, victim->coords, 128.);
2727 victim->skeleton.longdead = 0;
2728 victim->skeleton.free = 1;
2729 victim->skeleton.broken = 0;
2730 victim->skeleton.spinny = 1;
2732 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2733 victim->skeleton.joints[i].velchange = 0;
2734 victim->skeleton.joints[i].delay = 0;
2735 victim->skeleton.joints[i].locked = 0;
2736 //victim->skeleton.joints[i].velocity=0;
2742 Normalise(&relative);
2743 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2744 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2745 victim->skeleton.joints[i].position.y += relative.y * .3;
2746 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2747 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2749 victim->Puff(abdomen);
2750 victim->jointVel(abdomen).y = relative.y * 400;
2754 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2755 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2760 if (!Tutorial::active) {
2761 emit_sound_at(heavyimpactsound, coords, 128.);
2764 relative = victim->coords - coords;
2766 Normalise(&relative);
2767 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2768 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2770 victim->Puff(abdomen);
2771 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2775 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2776 victim->jointVel(abdomen) += relative * damagemult * 300;
2780 if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
2781 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2786 if (!Tutorial::active) {
2787 emit_sound_at(thudsound, coords);
2790 victim->skeleton.longdead = 0;
2791 victim->skeleton.free = 1;
2792 victim->skeleton.broken = 0;
2793 victim->skeleton.spinny = 1;
2795 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2796 victim->skeleton.joints[i].velchange = 0;
2797 //victim->skeleton.joints[i].delay=0;
2798 victim->skeleton.joints[i].locked = 0;
2801 relative = victim->coords - coords;
2802 Normalise(&relative);
2804 Normalise(&relative);
2805 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2806 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2808 if (!victim->dead) {
2812 victim->Puff(abdomen);
2813 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2814 victim->jointVel(abdomen) += relative * damagemult * 200;
2816 if (!victim->dead) {
2822 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2825 if (!victim->skeleton.free) {
2831 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2832 emit_sound_at(knifesheathesound, coords, 128.);
2835 if (victim && hasvictim) {
2836 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2838 XYZ where, startpoint, endpoint, movepoint, colpoint;
2839 float rotationpoint;
2841 if (weapons[weaponids[weaponactive]].getType() == knife) {
2842 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2843 where -= victim->coords;
2844 if (!victim->skeleton.free) {
2845 where = DoRotation(where, 0, -victim->yaw, 0);
2849 startpoint.y += 100;
2853 if (weapons[weaponids[weaponactive]].getType() == sword) {
2854 where = weapons[weaponids[weaponactive]].position;
2855 where -= victim->coords;
2856 if (!victim->skeleton.free) {
2857 where = DoRotation(where, 0, -victim->yaw, 0);
2860 where = weapons[weaponids[weaponactive]].tippoint;
2861 where -= victim->coords;
2862 if (!victim->skeleton.free) {
2863 where = DoRotation(where, 0, -victim->yaw, 0);
2867 if (weapons[weaponids[weaponactive]].getType() == staff) {
2868 where = weapons[weaponids[weaponactive]].position;
2869 where -= victim->coords;
2870 if (!victim->skeleton.free) {
2871 where = DoRotation(where, 0, -victim->yaw, 0);
2874 where = weapons[weaponids[weaponactive]].tippoint;
2875 where -= victim->coords;
2876 if (!victim->skeleton.free) {
2877 where = DoRotation(where, 0, -victim->yaw, 0);
2883 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2885 if (whichtri != -1) {
2886 if (victim->dead != 2) {
2887 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2888 if (!victim->dead) {
2889 award_bonus(id, FinishedBonus);
2893 weapons[weaponids[weaponactive]].bloody = 2;
2896 victim->skeleton.longdead = 0;
2897 victim->skeleton.free = 1;
2898 victim->skeleton.broken = 0;
2900 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2901 victim->skeleton.joints[i].velchange = 0;
2902 victim->skeleton.joints[i].locked = 0;
2903 //victim->skeleton.joints[i].velocity=0;
2905 emit_sound_at(fleshstabsound, coords, 128);
2907 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2908 weapons[weaponids[weaponactive]].blooddrip += 5;
2909 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2911 if (whichtri == -1) {
2913 emit_sound_at(knifesheathesound, coords, 128.);
2919 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
2921 emit_sound_at(knifedrawsound, coords, 128);
2924 if (victim && hasvictim) {
2925 XYZ footvel, footpoint;
2927 emit_sound_at(fleshstabremovesound, coords, 128.);
2930 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2932 if (weapons[weaponids[weaponactive]].getType() == sword) {
2933 XYZ where, startpoint, endpoint, movepoint;
2934 float rotationpoint;
2937 where = weapons[weaponids[weaponactive]].position;
2938 where -= victim->coords;
2939 if (!victim->skeleton.free) {
2940 where = DoRotation(where, 0, -victim->yaw, 0);
2943 where = weapons[weaponids[weaponactive]].tippoint;
2944 where -= victim->coords;
2945 if (!victim->skeleton.free) {
2946 where = DoRotation(where, 0, -victim->yaw, 0);
2952 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2953 footpoint += victim->coords;
2955 if (whichtri == -1) {
2956 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2959 if (weapons[weaponids[weaponactive]].getType() == staff) {
2960 XYZ where, startpoint, endpoint, movepoint;
2961 float rotationpoint;
2964 where = weapons[weaponids[weaponactive]].position;
2965 where -= victim->coords;
2966 if (!victim->skeleton.free) {
2967 where = DoRotation(where, 0, -victim->yaw, 0);
2970 where = weapons[weaponids[weaponactive]].tippoint;
2971 where -= victim->coords;
2972 if (!victim->skeleton.free) {
2973 where = DoRotation(where, 0, -victim->yaw, 0);
2979 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2980 footpoint += victim->coords;
2982 if (whichtri == -1) {
2983 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2986 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2988 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2989 victim->skeleton.longdead = 0;
2990 victim->skeleton.free = 1;
2991 victim->skeleton.broken = 0;
2993 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2994 victim->skeleton.joints[i].velchange = 0;
2995 victim->skeleton.joints[i].locked = 0;
2996 //victim->skeleton.joints[i].velocity=0;
3002 Normalise(&relative);
3003 //victim->Puff(abdomen);
3005 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
3008 if (victim->bloodloss < victim->damagetolerance) {
3009 victim->bloodloss += 1000;
3013 victim->jointVel(abdomen) += relative * damagemult * 20;
3017 if (!hasvictim && onterrain) {
3018 weapons[weaponids[weaponactive]].bloody = 0;
3019 weapons[weaponids[weaponactive]].blooddrip = 0;
3023 if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3024 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
3033 if (!Tutorial::active) {
3034 emit_sound_at(heavyimpactsound, victim->coords, 128);
3039 relative = victim->coords - coords;
3041 Normalise(&relative);
3042 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3043 victim->skeleton.joints[i].velocity = relative * 30;
3045 victim->jointVel(head) += relative * damagemult * 150;
3047 victim->frameTarget = 0;
3048 victim->animTarget = staggerbackhardanim;
3049 victim->targetyaw = targetyaw + 180;
3051 victim->stunned = 1;
3054 victim->Puff(abdomen);
3055 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
3061 if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3062 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
3067 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
3068 if (!Tutorial::active) {
3069 emit_sound_at(thudsound, victim->coords);
3071 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
3072 if (!Tutorial::active) {
3073 emit_sound_at(whooshhitsound, victim->coords);
3076 if (!Tutorial::active) {
3077 emit_sound_at(heavyimpactsound, victim->coords);
3081 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight) {
3085 relative = victim->coords - coords;
3087 Normalise(&relative);
3089 Normalise(&relative);
3090 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3091 victim->skeleton.joints[i].velocity = relative * 5;
3093 victim->jointVel(abdomen) += relative * damagemult * 400;
3095 victim->frameTarget = 0;
3096 victim->animTarget = staggerbackhardanim;
3097 victim->targetyaw = targetyaw + 180;
3099 victim->stunned = 1;
3101 victim->Puff(abdomen);
3102 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
3108 if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3109 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3110 if (victim->id == 0) {
3113 emit_sound_at(landsound2, victim->coords);
3119 if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3120 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3121 if (victim->id == 0) {
3125 if (weaponactive != -1) {
3126 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3127 if (weapons[victim->weaponids[0]].getType() == staff) {
3128 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3130 if (weapons[weaponids[0]].getType() == staff) {
3131 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3134 emit_sound_at(swordstaffsound, victim->coords);
3136 emit_sound_at(metalhitsound, victim->coords);
3144 if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3145 if (weaponactive != -1) {
3148 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);
3150 weapons[weaponids[0]].thrown(aim * 50);
3153 weaponids[0] = weaponids[num_weapons];
3159 if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3161 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 && /*Animation::animations[victim->animTarget].height!=lowheight&&*/ victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
3163 if (!Tutorial::active) {
3164 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
3167 award_bonus(id, Slicebonus);
3168 if (!Tutorial::active) {
3169 emit_sound_at(knifeslicesound, victim->coords);
3171 //victim->jointVel(abdomen)+=relative*damagemult*200;
3172 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
3173 if (victim->id != 0 || difficulty == 2) {
3174 victim->frameTarget = 0;
3175 victim->animTarget = staggerbackhardanim;
3176 victim->targetyaw = targetyaw + 180;
3180 victim->lowreversaldelay = 0;
3181 victim->highreversaldelay = 0;
3182 if (aitype != playercontrolled) {
3183 weaponmissdelay = .6;
3186 if (!Tutorial::active) {
3187 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3188 weapons[weaponids[weaponactive]].bloody = 1;
3190 weapons[weaponids[weaponactive]].blooddrip += 3;
3193 XYZ footvel, footpoint;
3195 if (skeleton.free) {
3196 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3198 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3200 if (Tutorial::active) {
3201 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
3204 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
3206 footvel = DoRotation(facing, 0, 90, 0) * .8;
3207 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3208 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3209 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3210 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3212 victim->DoDamage(damagemult * 0);
3216 if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3217 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
3218 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
3219 award_bonus(id, Slashbonus);
3221 if (!Tutorial::active) {
3222 if (normaldotproduct(victim->facing, victim->coords - coords) < 0) {
3223 victim->DoBloodBig(2 / victim->armorhigh, 190);
3225 victim->DoBloodBig(2 / victim->armorhigh, 185);
3227 victim->deathbleeding = 1;
3228 emit_sound_at(swordslicesound, victim->coords);
3229 victim->frameTarget = 0;
3230 victim->animTarget = staggerbackhardanim;
3231 victim->targetyaw = targetyaw + 180;
3233 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3234 weapons[weaponids[weaponactive]].bloody = 1;
3236 weapons[weaponids[weaponactive]].blooddrip += 3;
3238 float bloodlossamount;
3239 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
3240 victim->bloodloss += bloodlossamount / victim->armorhigh;
3241 victim->DoDamage(damagemult * 0);
3243 XYZ footvel, footpoint;
3245 if (skeleton.free) {
3246 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3248 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3251 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3253 footvel = DoRotation(facing, 0, 90, 0) * .8;
3255 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3256 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3257 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3258 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3261 if (victim->weaponactive != -1) {
3262 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3263 if (weapons[victim->weaponids[0]].getType() == staff) {
3264 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3266 if (weapons[weaponids[0]].getType() == staff) {
3267 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3270 emit_sound_at(swordstaffsound, victim->coords);
3272 emit_sound_at(metalhitsound, victim->coords);
3277 victim->Puff(righthand);
3279 victim->frameTarget = 0;
3280 victim->animTarget = staggerbackhighanim;
3281 victim->targetyaw = targetyaw + 180;
3283 aim = DoRotation(facing, 0, 90, 0) * 21;
3285 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3286 victim->num_weapons--;
3287 if (victim->num_weapons) {
3288 victim->weaponids[0] = victim->weaponids[num_weapons];
3289 if (victim->weaponstuck == victim->num_weapons) {
3290 victim->weaponstuck = 0;
3293 victim->weaponactive = -1;
3294 for (unsigned i = 0; i < Person::players.size(); i++) {
3295 Person::players[i]->wentforweapon = 0;
3301 if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3302 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3303 if (!Tutorial::active) {
3304 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3309 if (Random() % 2 || creature == wolftype) {
3312 emit_sound_at(staffheadsound, victim->coords);
3316 relative = victim->coords - coords;
3318 Normalise(&relative);
3319 relative = DoRotation(relative, 0, 90, 0);
3321 Normalise(&relative);
3322 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3323 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3325 victim->jointVel(head) += relative * damagemult * 230;
3326 victim->jointVel(neck) += relative * damagemult * 230;
3328 if (!Tutorial::active) {
3329 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3331 award_bonus(id, solidhit, 30);
3336 if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3337 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3338 if (!Tutorial::active) {
3339 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3344 if (Random() % 2 || creature == wolftype) {
3347 emit_sound_at(staffheadsound, victim->coords);
3351 relative = victim->coords - coords;
3353 Normalise(&relative);
3354 relative = DoRotation(relative, 0, -90, 0);
3355 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3356 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3358 victim->jointVel(head) += relative * damagemult * 220;
3359 victim->jointVel(neck) += relative * damagemult * 220;
3361 if (!Tutorial::active) {
3362 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3364 award_bonus(id, solidhit, 60);
3369 if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3370 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3372 if (!Tutorial::active) {
3373 if (!victim->dead) {
3374 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3379 if (Random() % 2 || creature == wolftype) {
3382 emit_sound_at(staffbodysound, victim->coords);
3384 victim->skeleton.longdead = 0;
3385 victim->skeleton.free = 1;
3386 victim->skeleton.broken = 0;
3388 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3389 victim->skeleton.joints[i].velchange = 0;
3390 victim->skeleton.joints[i].locked = 0;
3391 //victim->skeleton.joints[i].velocity=0;
3398 Normalise(&relative);
3399 if (!victim->dead) {
3400 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3401 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3403 victim->jointVel(abdomen) += relative * damagemult * 40;
3406 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3407 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3410 victim->Puff(abdomen);
3411 if (!Tutorial::active) {
3412 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3414 if (!victim->dead) {
3415 award_bonus(id, solidhit, 40);
3421 if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3422 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3428 relative = victim->coords - coords;
3430 Normalise(&relative);
3434 if (Animation::animations[victim->animTarget].height == lowheight) {
3440 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3441 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3443 victim->jointVel(head) += relative * damagemult * 200;
3444 if (!Tutorial::active) {
3445 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3448 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3449 if (victim->howactive == typesleeping) {
3450 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3452 if (creature == wolftype) {
3453 emit_sound_at(clawslicesound, victim->coords, 128.);
3455 victim->DoBloodBig(2 / victim->armorhead, 175);
3458 if (victim->damage >= victim->damagetolerance) {
3461 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3462 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3464 victim->jointVel(abdomen) += relative * damagemult * 200;
3465 victim->frameTarget = 0;
3466 victim->animTarget = staggerbackhighanim;
3467 victim->targetyaw = targetyaw + 180;
3469 if (!Tutorial::active) {
3470 emit_sound_at(landsound2, victim->coords, 128.);
3472 victim->Puff(abdomen);
3473 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3474 if (creature == wolftype) {
3475 emit_sound_at(clawslicesound, victim->coords, 128.);
3477 victim->DoBloodBig(2 / victim->armorhigh, 170);
3483 if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3484 if ((victim->animTarget != jumpupanim) &&
3485 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3486 (victim != this->shared_from_this())) {
3491 if (!Tutorial::active) {
3492 emit_sound_at(landsound2, victim->coords, 128.);
3495 relative = victim->coords - coords;
3497 Normalise(&relative);
3499 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3502 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3503 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3505 relative = DoRotation(relative, 0, -90, 0);
3507 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3508 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) {
3509 victim->skeleton.joints[i].velocity = relative * 80;
3512 victim->Puff(rightankle);
3513 victim->Puff(leftankle);
3514 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3516 if (victim->damage >= victim->damagetolerance) {
3519 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3520 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3522 relative = DoRotation(relative, 0, -90, 0);
3523 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3524 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) {
3525 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3528 victim->jointVel(abdomen) += relative * damagemult * 200;
3529 victim->frameTarget = 0;
3530 victim->animTarget = staggerbackhighanim;
3531 victim->targetyaw = targetyaw + 180;
3533 if (!Tutorial::active) {
3534 emit_sound_at(landsound2, victim->coords, 128.);
3536 victim->Puff(abdomen);
3537 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3544 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3545 if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3554 if (!Tutorial::active) {
3555 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3557 if (creature == wolftype) {
3558 emit_sound_at(clawslicesound, victim->coords, 128);
3560 victim->DoBloodBig(2 / victim->armorhigh, 170);
3564 relative = victim->coords - oldcoords;
3566 Normalise(&relative);
3567 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3568 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3570 victim->jointVel(abdomen) += relative * damagemult * 200;
3571 victim->Puff(abdomen);
3572 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3574 award_bonus(id, Reversal);
3577 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3578 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3579 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3580 takeWeapon(victim->weaponids[victim->weaponactive]);
3581 victim->num_weapons--;
3582 if (victim->num_weapons > 0) {
3583 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3585 victim->weaponactive = -1;
3590 if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3599 emit_sound_at(whooshhitsound, victim->coords, 128.);
3602 relative = victim->coords - oldcoords;
3604 Normalise(&relative);
3605 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3606 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3608 victim->jointVel(abdomen) += relative * damagemult * 200;
3610 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3613 if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3623 award_bonus(id, staffreversebonus);
3625 if (!Tutorial::active) {
3626 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3629 award_bonus(id, staffreversebonus); // Huh, again?
3632 relative = victim->coords - oldcoords;
3634 Normalise(&relative);
3635 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3636 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3638 victim->jointVel(abdomen) += relative * damagemult * 200;
3640 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3643 if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3649 Normalise(&relative);
3651 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3652 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3654 victim->jointVel(lefthand) *= .1;
3655 victim->jointVel(leftwrist) *= .2;
3656 victim->jointVel(leftelbow) *= .5;
3657 victim->jointVel(leftshoulder) *= .7;
3658 victim->jointVel(righthand) *= .1;
3659 victim->jointVel(rightwrist) *= .2;
3660 victim->jointVel(rightelbow) *= .5;
3661 victim->jointVel(rightshoulder) *= .7;
3663 victim->Puff(abdomen);
3664 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3666 award_bonus(id, Reversal);
3670 if (weaponactive != -1 || creature == wolftype) {
3673 if (creature == rabbittype && weaponactive != -1) {
3674 if (weapons[weaponids[0]].getType() == staff) {
3679 if (weaponactive != -1) {
3680 victim->DoBloodBig(2 / victim->armorhigh, 225);
3681 emit_sound_at(knifeslicesound, victim->coords);
3682 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3683 weapons[weaponids[weaponactive]].bloody = 1;
3685 weapons[weaponids[weaponactive]].blooddrip += 3;
3687 if (weaponactive == -1 && creature == wolftype) {
3688 emit_sound_at(clawslicesound, victim->coords, 128.);
3690 victim->DoBloodBig(2 / victim->armorhigh, 175);
3695 if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3701 Normalise(&relative);
3703 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3704 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3706 victim->jointVel(lefthand) *= .1 - 1;
3707 victim->jointVel(leftwrist) *= .2 - 1;
3708 victim->jointVel(leftelbow) *= .5 - 1;
3709 victim->jointVel(leftshoulder) *= .7 - 1;
3710 victim->jointVel(righthand) *= .1 - 1;
3711 victim->jointVel(rightwrist) *= .2 - 1;
3712 victim->jointVel(rightelbow) *= .5 - 1;
3713 victim->jointVel(rightshoulder) *= .7 - 1;
3715 award_bonus(id, swordreversebonus);
3718 if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3727 if (!Tutorial::active) {
3728 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3732 relative = victim->coords - oldcoords;
3734 Normalise(&relative);
3735 relative = DoRotation(relative, 0, -90, 0);
3736 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3737 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3739 victim->jointVel(abdomen) += relative * damagemult * 200;
3740 victim->Puff(abdomen);
3741 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3743 award_bonus(id, Reversal);
3746 if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3749 victim->skeleton.spinny = 0;
3751 relative = facing * -1;
3753 Normalise(&relative);
3754 if (victim->id == 0) {
3757 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3758 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3760 victim->damage = victim->damagetolerance;
3761 victim->permanentdamage = victim->damagetolerance - 1;
3764 if (weaponactive != -1 || creature == wolftype) {
3767 if (creature == rabbittype && weaponactive != -1) {
3768 if (weapons[weaponids[0]].getType() == staff) {
3773 if (weaponactive != -1) {
3774 victim->DoBloodBig(200, 225);
3775 emit_sound_at(knifeslicesound, victim->coords);
3777 weapons[weaponids[weaponactive]].bloody = 2;
3779 weapons[weaponids[weaponactive]].blooddrip += 5;
3782 if (creature == wolftype && weaponactive == -1) {
3783 emit_sound_at(clawslicesound, victim->coords, 128.);
3785 victim->DoBloodBig(2, 175);
3788 award_bonus(id, spinecrusher);
3791 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3792 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3794 if (animTarget == knifefollowanim) {
3795 victim->DoBloodBig(200, 210);
3797 if (animTarget == knifesneakattackanim) {
3798 XYZ footvel, footpoint;
3800 footpoint = weapons[weaponids[0]].tippoint;
3802 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3804 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3805 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3806 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3807 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3808 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3809 victim->DoBloodBig(200, 195);
3810 award_bonus(id, tracheotomy);
3812 if (animTarget == knifefollowanim) {
3813 award_bonus(id, Stabbonus);
3814 XYZ footvel, footpoint;
3816 footpoint = weapons[weaponids[0]].tippoint;
3818 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3820 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3821 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3822 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3823 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3824 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3826 victim->bloodloss += 10000;
3827 victim->velocity = 0;
3828 emit_sound_at(fleshstabsound, victim->coords);
3830 weapons[weaponids[weaponactive]].bloody = 2;
3832 weapons[weaponids[weaponactive]].blooddrip += 5;
3836 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3838 victim->velocity = 0;
3839 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3840 victim->skeleton.joints[i].velocity = 0;
3842 if (animTarget == knifefollowanim) {
3844 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3845 victim->skeleton.joints[i].velocity = 0;
3848 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3849 emit_sound_at(fleshstabremovesound, victim->coords);
3851 weapons[weaponids[weaponactive]].bloody = 2;
3853 weapons[weaponids[weaponactive]].blooddrip += 5;
3855 XYZ footvel, footpoint;
3857 footpoint = weapons[weaponids[0]].tippoint;
3859 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3861 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3862 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3863 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3864 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3865 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3869 if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3870 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3871 award_bonus(id, backstab);
3875 XYZ footvel, footpoint;
3877 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3879 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3881 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3882 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3883 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3884 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3885 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3886 victim->DoBloodBig(200, 180);
3887 victim->DoBloodBig(200, 215);
3888 victim->bloodloss += 10000;
3889 victim->velocity = 0;
3890 emit_sound_at(fleshstabsound, victim->coords);
3892 weapons[weaponids[weaponactive]].bloody = 2;
3894 weapons[weaponids[weaponactive]].blooddrip += 5;
3898 if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3900 victim->velocity = 0;
3901 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3902 victim->skeleton.joints[i].velocity = 0;
3904 if (weaponactive != -1) {
3905 emit_sound_at(fleshstabremovesound, victim->coords);
3907 weapons[weaponids[weaponactive]].bloody = 2;
3909 weapons[weaponids[weaponactive]].blooddrip += 5;
3911 XYZ footvel, footpoint;
3913 footpoint = weapons[weaponids[0]].tippoint;
3915 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3917 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3918 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3919 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3920 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3921 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3925 if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3934 if (weaponactive == -1) {
3935 if (!Tutorial::active) {
3936 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3941 if (weaponactive != -1 || creature == wolftype) {
3944 if (creature == rabbittype && weaponactive != -1) {
3945 if (weapons[weaponids[0]].getType() == staff) {
3950 if (weaponactive != -1) {
3951 victim->DoBloodBig(2 / victim->armorhead, 225);
3952 emit_sound_at(knifeslicesound, victim->coords);
3953 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3954 weapons[weaponids[weaponactive]].bloody = 1;
3956 weapons[weaponids[weaponactive]].blooddrip += 3;
3958 if (weaponactive == -1 && creature == wolftype) {
3959 emit_sound_at(clawslicesound, victim->coords, 128.);
3961 victim->DoBloodBig(2 / victim->armorhead, 175);
3965 award_bonus(id, Reversal);
3970 relative = facing * -1;
3972 Normalise(&relative);
3973 relative = DoRotation(relative, 0, 90, 0);
3975 Normalise(&relative);
3976 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3977 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3979 victim->jointVel(head) += relative * damagemult * 200;
3980 if (victim->damage < victim->damagetolerance - 100) {
3981 victim->velocity = relative * 200;
3983 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3984 victim->velocity = 0;
3987 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))) {
3991 relative = facing * -1;
3993 Normalise(&relative);
3994 relative = DoRotation(relative, 0, 90, 0);
3996 Normalise(&relative);
3997 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3998 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
4000 victim->jointVel(head) += relative * damagemult * 200;
4003 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim)) {
4004 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
4005 award_bonus(id, reverseko);
4011 if (frameTarget > int(Animation::animations[animCurrent].frames.size()) - 1) {
4014 animTarget = getIdle();
4015 FootLand(leftfoot, 1);
4016 FootLand(rightfoot, 1);
4018 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
4019 animTarget = rollanim;
4021 emit_sound_at(movewhooshsound, coords, 128.);
4023 if (animCurrent == staggerbackhighanim) {
4024 animTarget = getIdle();
4026 if (animCurrent == staggerbackhardanim) {
4027 animTarget = getIdle();
4029 if (animCurrent == removeknifeanim) {
4030 animTarget = getIdle();
4032 if (animCurrent == crouchremoveknifeanim) {
4033 animTarget = getCrouch();
4035 if (animCurrent == backhandspringanim) {
4036 animTarget = getIdle();
4038 if (animCurrent == dodgebackanim) {
4039 animTarget = getIdle();
4041 if (animCurrent == drawleftanim) {
4042 animTarget = getIdle();
4044 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
4045 animTarget = getIdle();
4046 if (animCurrent == crouchdrawrightanim) {
4047 animTarget = getCrouch();
4049 if (weaponactive == -1) {
4051 } else if (weaponactive == 0) {
4053 if (num_weapons == 2) {
4055 buffer = weaponids[0];
4056 weaponids[0] = weaponids[1];
4057 weaponids[1] = buffer;
4061 if (weaponactive == -1) {
4062 emit_sound_at(knifesheathesound, coords, 128.);
4064 if (weaponactive != -1) {
4065 emit_sound_at(knifedrawsound, coords, 128.);
4068 if (animCurrent == rollanim) {
4069 animTarget = getCrouch();
4070 FootLand(leftfoot, 1);
4071 FootLand(rightfoot, 1);
4074 if (animTarget == walljumprightkickanim) {
4077 if (animTarget == walljumpleftkickanim) {
4080 animTarget = jumpdownanim;
4082 if (animCurrent == climbanim) {
4083 animTarget = getCrouch();
4085 coords += facing * .1;
4086 if (!isnormal(coords.x)) {
4097 if (animTarget == rabbitkickreversalanim) {
4098 animTarget = getCrouch();
4101 if (animTarget == jumpreversalanim) {
4102 animTarget = getCrouch();
4105 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
4106 if (attackkeydown && animTarget != walljumpfrontanim) {
4108 float closestdist = -1;
4110 if (Person::players.size() > 1) {
4111 for (unsigned i = 0; i < Person::players.size(); i++) {
4112 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4113 distance = distsq(&Person::players[i]->coords, &coords);
4114 if (closestdist == -1 || distance < closestdist) {
4115 closestdist = distance;
4121 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4122 victim = Person::players[closest];
4123 animTarget = walljumprightkickanim;
4125 XYZ rotatetarget = victim->coords - coords;
4126 Normalise(&rotatetarget);
4127 yaw = -asin(0 - rotatetarget.x);
4129 if (rotatetarget.z < 0) {
4132 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4133 velocity = (victim->coords - coords) * 4;
4138 if (animTarget == walljumpbackanim) {
4139 animTarget = backflipanim;
4141 velocity = facing * -8;
4144 resume_stream(whooshsound);
4147 if (animTarget == walljumprightanim) {
4148 animTarget = rightflipanim;
4152 velocity = DoRotation(facing, 0, 30, 0) * -8;
4155 if (animTarget == walljumpfrontanim) {
4156 animTarget = frontflipanim;
4160 velocity = facing * 8;
4164 resume_stream(whooshsound);
4167 if (animTarget == walljumpleftanim) {
4168 if (attackkeydown) {
4170 float closestdist = -1;
4172 if (Person::players.size() > 1) {
4173 for (unsigned i = 0; i < Person::players.size(); i++) {
4174 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4175 distance = distsq(&Person::players[i]->coords, &coords);
4176 if (closestdist == -1 || distance < closestdist) {
4177 closestdist = distance;
4183 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4184 victim = Person::players[closest];
4185 animTarget = walljumpleftkickanim;
4187 XYZ rotatetarget = victim->coords - coords;
4188 Normalise(&rotatetarget);
4189 yaw = -asin(0 - rotatetarget.x);
4191 if (rotatetarget.z < 0) {
4194 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4195 velocity = (victim->coords - coords) * 4;
4200 if (animTarget != walljumpleftkickanim) {
4201 animTarget = leftflipanim;
4205 velocity = DoRotation(facing, 0, -30, 0) * -8;
4209 resume_stream(whooshsound);
4212 if (animTarget == sneakattackanim) {
4213 animCurrent = getCrouch();
4214 animTarget = getCrouch();
4221 transspeed = 1000000;
4222 targetheadyaw += 180;
4223 coords -= facing * .7;
4225 coords.y = terrain.getHeight(coords.x, coords.z);
4230 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
4231 animTarget = getIdle();
4234 coords.y = terrain.getHeight(coords.x, coords.z);
4239 if (animCurrent == knifefollowanim) {
4240 animTarget = getIdle();
4243 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
4244 float ycoords = oldcoords.y;
4245 animTarget = getStop();
4250 transspeed = 1000000;
4251 targetheadyaw += 180;
4252 if (!isnormal(coords.x)) {
4255 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim) {
4256 oldcoords = coords + facing * .5;
4257 } else if (animCurrent == sweepreversalanim) {
4258 oldcoords = coords + facing * 1.1;
4259 } else if (animCurrent == upunchreversalanim) {
4260 oldcoords = coords + facing * 1.5;
4263 targetheadyaw += 180;
4266 } else if (animCurrent == knifeslashreversalanim) {
4267 oldcoords = coords + facing * .5;
4270 targetheadyaw += 90;
4273 } else if (animCurrent == staffspinhitreversalanim) {
4276 targetheadyaw += 180;
4281 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
4283 oldcoords.y = ycoords;
4285 currentoffset = coords - oldcoords;
4291 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4296 if (Animation::animations[animTarget].attack == reversed) {
4298 if (animTarget == sweepreversedanim) {
4301 animTarget = backhandspringanim;
4303 emit_sound_at(landsound, coords, 128);
4305 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4306 animTarget = rollanim;
4309 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4310 coords.y = oldcoords.y;
4312 if (animCurrent == knifeslashreversedanim) {
4313 animTarget = rollanim;
4318 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4319 coords.y = oldcoords.y;
4323 animTarget = jumpdownanim;
4326 animTarget = getIdle();
4328 if (wasLandhard()) {
4329 animTarget = getIdle();
4331 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4332 animTarget = getIdle();
4334 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4335 coords.y = oldcoords.y;
4336 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4337 targetoffset.y = coords.y;
4339 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4341 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4342 currentoffset.y -= (coords.y - targetoffset.y);
4343 coords.y = targetoffset.y;
4345 normalsupdatedelay = 0;
4347 if (animCurrent == upunchanim) {
4348 animTarget = getStop();
4349 normalsupdatedelay = 0;
4352 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4356 if (num_weapons > 0) {
4357 if (weapons[0].getType() == staff) {
4366 rabbitkickragdoll = 1;
4368 if (animCurrent == rabbitkickreversedanim) {
4374 skeleton.spinny = 0;
4375 SolidHitBonus(!id); // FIXME: tricky id
4379 animTarget = rollanim;
4382 pause_sound(whooshsound);
4387 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4391 skeleton.spinny = 0;
4393 if (animCurrent == jumpreversedanim) {
4399 skeleton.spinny = 0;
4400 SolidHitBonus(!id); // FIXME: tricky id
4404 animTarget = rollanim;
4405 coords += facing * 2;
4407 pause_sound(whooshsound);
4413 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) {
4414 animTarget = getupfromfrontanim;
4416 } else if (Animation::animations[animCurrent].attack == normalattack) {
4417 animTarget = getIdle();
4420 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4421 animTarget = blockhighleftstrikeanim;
4423 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4424 animTarget = getIdle();
4427 if (animCurrent == spinkickanim && victim->skeleton.free) {
4428 if (creature == rabbittype) {
4429 animTarget = fightidleanim;
4435 if (isIdle() && !wasIdle()) {
4436 normalsupdatedelay = 0;
4439 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4440 animTarget = jumpdownanim;
4443 if (!skeleton.free) {
4445 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4446 if (!isRun() || !wasRun()) {
4447 if (targetFrame().speed > currentFrame().speed) {
4448 target += multiplier * targetFrame().speed * speed * 2;
4450 if (targetFrame().speed <= currentFrame().speed) {
4451 target += multiplier * currentFrame().speed * speed * 2;
4454 if (isRun() && wasRun()) {
4456 tempspeed = velspeed;
4457 if (tempspeed < 10 * speedmult) {
4458 tempspeed = 10 * speedmult;
4460 /* FIXME - mixed of target and current here, is that intended? */
4461 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4463 } else if (transspeed) {
4464 target += multiplier * transspeed * speed * 2;
4466 if (!isRun() || !wasRun()) {
4467 if (targetFrame().speed > currentFrame().speed) {
4468 target += multiplier * targetFrame().speed * 2;
4470 if (targetFrame().speed <= currentFrame().speed) {
4471 target += multiplier * currentFrame().speed * 2;
4476 if (animCurrent != animTarget) {
4477 target = (target + oldtarget) / 2;
4481 frameCurrent = frameTarget;
4485 rot = targetrot * target;
4486 yaw += rot - oldrot;
4492 if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
4493 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4495 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4497 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4498 skeleton.joints[i].position = currentFrame().joints[i].position;
4501 skeleton.FindForwards();
4503 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4504 if (skeleton.muscles[i].visible) {
4505 skeleton.FindRotationMuscle(i, animTarget);
4508 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4509 if (skeleton.muscles[i].visible) {
4510 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4511 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4513 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4514 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4516 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4517 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4523 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4524 skeleton.joints[i].position = targetFrame().joints[i].position;
4527 skeleton.FindForwards();
4529 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4530 if (skeleton.muscles[i].visible) {
4531 skeleton.FindRotationMuscle(i, animTarget);
4534 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4535 if (skeleton.muscles[i].visible) {
4536 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4537 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4539 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4540 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4542 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4543 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4545 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) {
4546 skeleton.muscles[i].newrotate3 -= 360;
4548 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) {
4549 skeleton.muscles[i].newrotate3 += 360;
4551 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) {
4552 skeleton.muscles[i].newrotate2 -= 360;
4554 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) {
4555 skeleton.muscles[i].newrotate2 += 360;
4557 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) {
4558 skeleton.muscles[i].newrotate1 -= 360;
4560 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) {
4561 skeleton.muscles[i].newrotate1 += 360;
4567 oldanimCurrent = animCurrent;
4568 oldanimTarget = animTarget;
4569 oldframeTarget = frameTarget;
4570 oldframeCurrent = frameCurrent;
4572 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4573 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target - skeleton.joints[i].position) / multiplier;
4574 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target;
4576 offset = currentoffset * (1 - target) + targetoffset * target;
4577 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4578 if (skeleton.muscles[i].visible) {
4579 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * target;
4580 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * target;
4581 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * target;
4586 if (isLanding() && landhard) {
4590 animTarget = getLandhard();
4603 void Person::DoStuff()
4605 static XYZ terrainnormal;
4606 static XYZ flatfacing;
4607 static XYZ flatvelocity;
4608 static float flatvelspeed;
4609 static int bloodsize;
4610 static int startx, starty, endx, endy;
4611 static GLubyte color;
4612 static XYZ bloodvel;
4614 onfiredelay -= multiplier;
4615 if (onfiredelay < 0 && onfire) {
4616 if (Random() % 2 == 0) {
4622 crouchkeydowntime += multiplier;
4623 if (!crouchkeydown) {
4624 crouchkeydowntime = 0;
4626 jumpkeydowntime += multiplier;
4627 if (!jumpkeydown && skeleton.free) {
4628 jumpkeydowntime = 0;
4631 if (hostile || damage > 0 || bloodloss > 0) {
4635 if (isIdle() || isRun()) {
4639 if (num_weapons == 1 && weaponactive != -1) {
4644 blooddimamount -= multiplier * .3;
4646 speechdelay -= multiplier;
4647 texupdatedelay -= multiplier;
4648 interestdelay -= multiplier;
4649 flamedelay -= multiplier;
4650 parriedrecently -= multiplier;
4652 victim = this->shared_from_this();
4657 speed = 1.1 * speedmult;
4659 speed = 1.0 * speedmult;
4661 if (!skeleton.free) {
4662 rabbitkickragdoll = 0;
4667 if (id != 0 && (creature == rabbittype || difficulty != 2)) {
4670 if (id != 0 && creature == wolftype && difficulty == 2) {
4672 if (aitype != passivetype) {
4674 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) {
4681 if (animTarget == wolfrunninganim && !superruntoggle) {
4682 animTarget = getRun();
4686 if (weaponactive == -1 && num_weapons > 0) {
4687 if (weapons[weaponids[0]].getType() == staff) {
4693 burnt += multiplier;
4698 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4700 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4707 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
4708 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4712 while (flamedelay < 0 && onfire) {
4714 int howmany = fabs(Random() % (skeleton.joints.size()));
4715 if (skeleton.free) {
4716 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4717 flatfacing = skeleton.joints[howmany].position * scale + coords;
4719 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4720 flatvelocity = (coords - oldcoords) / multiplier / 2;
4722 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4725 while (flamedelay < 0 && !onfire && Tutorial::active && id != 0) {
4727 int howmany = fabs(Random() % (skeleton.joints.size()));
4728 if (skeleton.free) {
4729 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4730 flatfacing = skeleton.joints[howmany].position * scale + coords;
4732 flatvelocity = (coords - oldcoords) / multiplier / 2;
4733 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4735 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4739 bleeding -= multiplier * .3;
4740 if (bloodtoggle == 2) {
4741 skeleton.drawmodel.textureptr.bind();
4742 if ((bleeding <= 0) && (detail != 2)) {
4748 if (neckspurtamount > 0) {
4749 neckspurtamount -= multiplier;
4750 neckspurtdelay -= multiplier * 3;
4751 neckspurtparticledelay -= multiplier * 3;
4752 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4755 if (skeleton.free) {
4756 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4757 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4758 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4760 bloodvel.z = 5 * neckspurtamount;
4761 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4762 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4763 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4765 neckspurtparticledelay = .05;
4767 if (neckspurtdelay < 0) {
4772 if (deathbleeding > 0 && dead != 2) {
4773 if (deathbleeding < 5) {
4774 bleeddelay -= deathbleeding * multiplier / 4;
4776 bleeddelay -= 5 * multiplier / 4;
4778 if (bleeddelay < 0 && bloodtoggle) {
4783 if (skeleton.free) {
4784 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4785 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4787 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4788 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4792 bloodloss += deathbleeding * multiplier * 80;
4793 deathbleeding -= multiplier * 1.6;
4794 if (deathbleeding < 0) {
4797 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4798 if (weaponactive != -1) {
4799 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4800 weapons[weaponids[0]].velocity.x += .01;
4803 weaponids[0] = weaponids[num_weapons];
4804 if (weaponstuck == num_weapons) {
4809 for (unsigned i = 0; i < Person::players.size(); i++) {
4810 Person::players[i]->wentforweapon = 0;
4818 if (!dead && creature == wolftype) {
4819 award_bonus(0, Wolfbonus);
4822 if (animTarget == knifefollowedanim && !skeleton.free) {
4823 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4824 skeleton.joints[i].velocity = 0;
4825 skeleton.joints[i].velocity.y = -2;
4828 if (id != 0 && unconscioustime > .1) {
4836 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4837 texupdatedelay = .12;
4839 bloodsize = 5 - realtexdetail;
4843 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4844 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4845 endx = startx + bloodsize;
4846 endy = starty + bloodsize;
4856 if (endx > skeleton.skinsize - 1) {
4857 endx = skeleton.skinsize - 1;
4860 if (endy > skeleton.skinsize - 1) {
4861 endy = skeleton.skinsize - 1;
4864 if (endx < startx) {
4867 if (endy < starty) {
4871 for (int i = startx; i < endx; i++) {
4872 for (int j = starty; j < endy; j++) {
4873 if (Random() % 2 == 0) {
4874 color = Random() % 85 + 170;
4875 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2) {
4876 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4878 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4879 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4884 skeleton.drawmodel.textureptr.bind();
4888 if (skeleton.free) {
4889 bleedx += 4 * direction / realtexdetail;
4891 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4893 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4896 bleedy -= 4 / realtexdetail;
4898 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4900 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4905 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4906 righthandmorphness = targetrighthandmorphness;
4907 righthandmorphstart = righthandmorphend;
4908 } else if (righthandmorphness > targetrighthandmorphness) {
4909 righthandmorphness -= multiplier * 4;
4910 } else if (righthandmorphness < targetrighthandmorphness) {
4911 righthandmorphness += multiplier * 4;
4914 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4915 lefthandmorphness = targetlefthandmorphness;
4916 lefthandmorphstart = lefthandmorphend;
4917 } else if (lefthandmorphness > targetlefthandmorphness) {
4918 lefthandmorphness -= multiplier * 4;
4919 } else if (lefthandmorphness < targetlefthandmorphness) {
4920 lefthandmorphness += multiplier * 4;
4923 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4924 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4925 tailmorphness = targettailmorphness;
4926 tailmorphstart = tailmorphend;
4927 } else if (tailmorphness > targettailmorphness) {
4928 tailmorphness -= multiplier * 10;
4929 } else if (tailmorphness < targettailmorphness) {
4930 tailmorphness += multiplier * 10;
4934 if (creature == wolftype) {
4935 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4936 tailmorphness = targettailmorphness;
4937 tailmorphstart = tailmorphend;
4938 } else if (tailmorphness > targettailmorphness) {
4939 tailmorphness -= multiplier * 2;
4940 } else if (tailmorphness < targettailmorphness) {
4941 tailmorphness += multiplier * 2;
4945 if (headmorphend == 3 || headmorphstart == 3) {
4946 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4947 headmorphness = targetheadmorphness;
4948 headmorphstart = headmorphend;
4949 } else if (headmorphness > targetheadmorphness) {
4950 headmorphness -= multiplier * 7;
4951 } else if (headmorphness < targetheadmorphness) {
4952 headmorphness += multiplier * 7;
4954 } else if (headmorphend == 5 || headmorphstart == 5) {
4955 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4956 headmorphness = targetheadmorphness;
4957 headmorphstart = headmorphend;
4958 } else if (headmorphness > targetheadmorphness) {
4959 headmorphness -= multiplier * 10;
4960 } else if (headmorphness < targetheadmorphness) {
4961 headmorphness += multiplier * 10;
4964 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4965 headmorphness = targetheadmorphness;
4966 headmorphstart = headmorphend;
4967 } else if (headmorphness > targetheadmorphness) {
4968 headmorphness -= multiplier * 4;
4969 } else if (headmorphness < targetheadmorphness) {
4970 headmorphness += multiplier * 4;
4974 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4975 chestmorphness = targetchestmorphness;
4976 chestmorphstart = chestmorphend;
4977 } else if (chestmorphness > targetchestmorphness) {
4978 chestmorphness -= multiplier;
4979 } else if (chestmorphness < targetchestmorphness) {
4980 chestmorphness += multiplier;
4983 if (dead != 2 && howactive <= typesleeping) {
4984 if (chestmorphstart == 0 && chestmorphend == 0) {
4986 targetchestmorphness = 1;
4989 if (chestmorphstart != 0 && chestmorphend != 0) {
4991 targetchestmorphness = 1;
4993 if (environment == snowyenvironment) {
4996 if (skeleton.free) {
4997 footvel = skeleton.specialforward[0] * -1;
4998 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
5000 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
5001 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
5003 if (animTarget == sleepanim) {
5004 footvel = DoRotation(footvel, 0, 90, 0);
5006 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
5010 if (!dead && howactive < typesleeping) {
5011 blinkdelay -= multiplier * 2;
5012 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
5014 targetheadmorphness = 1;
5016 blinkdelay = (float)(abs(Random() % 40)) / 5;
5018 if (headmorphstart == 3 && headmorphend == 3) {
5020 targetheadmorphness = 1;
5025 twitchdelay -= multiplier * 1.5;
5026 if (animTarget != hurtidleanim) {
5027 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
5029 targetheadmorphness = 1;
5031 twitchdelay = (float)(abs(Random() % 40)) / 5;
5033 if (headmorphstart == 5 && headmorphend == 5) {
5035 targetheadmorphness = 1;
5039 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
5040 twitchdelay3 -= multiplier * 1;
5041 if (Random() % 2 == 0) {
5042 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
5043 righthandmorphness = 0;
5044 targetrighthandmorphness = 1;
5045 righthandmorphend = 1;
5046 if (Random() % 2 == 0) {
5047 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
5050 if (righthandmorphstart == 1 && righthandmorphend == 1) {
5051 righthandmorphness = 0;
5052 targetrighthandmorphness = 1;
5053 righthandmorphend = 0;
5056 if (Random() % 2 == 0) {
5057 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
5058 lefthandmorphness = 0;
5059 targetlefthandmorphness = 1;
5060 lefthandmorphend = 1;
5061 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
5063 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
5064 lefthandmorphness = 0;
5065 targetlefthandmorphness = 1;
5066 lefthandmorphend = 0;
5072 if (creature == rabbittype) {
5073 if (howactive < typesleeping) {
5074 twitchdelay2 -= multiplier * 1.5;
5076 twitchdelay2 -= multiplier * 0.5;
5078 if (howactive <= typesleeping) {
5079 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
5081 targettailmorphness = 1;
5083 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
5085 if (tailmorphstart == 1 && tailmorphend == 1) {
5087 targettailmorphness = 1;
5090 if (tailmorphstart == 2 && tailmorphend == 2) {
5092 targettailmorphness = 1;
5099 if (creature == wolftype) {
5100 twitchdelay2 -= multiplier * 1.5;
5101 if (tailmorphend != 0) {
5102 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
5104 targettailmorphness = 1;
5109 if (tailmorphend != 5) {
5110 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
5112 targettailmorphness = 1;
5117 if (twitchdelay2 <= 0) {
5118 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
5120 targettailmorphness = 1;
5123 if (tailmorphstart == 1 && tailmorphend == 1) {
5125 targettailmorphness = 1;
5128 if (tailmorphstart == 2 && tailmorphend == 2) {
5130 targettailmorphness = 1;
5133 if (tailmorphstart == 3 && tailmorphend == 3) {
5135 targettailmorphness = 1;
5138 if (tailmorphstart == 4 && tailmorphend == 4) {
5140 targettailmorphness = 1;
5147 unconscioustime = 0;
5150 if (dead == 1 || howactive == typesleeping) {
5151 unconscioustime += multiplier;
5152 //If unconscious, close eyes and mouth
5153 if (righthandmorphend != 0) {
5154 righthandmorphness = 0;
5156 righthandmorphend = 0;
5157 targetrighthandmorphness = 1;
5159 if (lefthandmorphend != 0) {
5160 lefthandmorphness = 0;
5162 lefthandmorphend = 0;
5163 targetlefthandmorphness = 1;
5165 if (headmorphend != 3 && headmorphend != 5) {
5169 targetheadmorphness = 1;
5172 if (howactive > typesleeping) {
5175 if (bloodtoggle && !bled) {
5176 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5177 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5178 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5179 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5183 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5189 if (dead == 2 || howactive > typesleeping) {
5190 //If dead, open mouth and hands
5191 if (righthandmorphend != 0) {
5192 righthandmorphness = 0;
5194 righthandmorphend = 0;
5195 targetrighthandmorphness = 1;
5197 if (lefthandmorphend != 0) {
5198 lefthandmorphness = 0;
5200 lefthandmorphend = 0;
5201 targetlefthandmorphness = 1;
5203 if (headmorphend != 2) {
5207 targetheadmorphness = 1;
5210 if (stunned > 0 && !dead && headmorphend != 2) {
5211 if (headmorphend != 4) {
5215 targetheadmorphness = 1;
5218 if (damage > damagetolerance && !dead) {
5221 unconscioustime = 0;
5223 if (creature == wolftype) {
5224 award_bonus(0, Wolfbonus);
5229 if (weaponactive != -1) {
5230 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5231 weapons[weaponids[0]].velocity.x += .01;
5234 weaponids[0] = weaponids[num_weapons];
5235 if (weaponstuck == num_weapons) {
5240 for (unsigned i = 0; i < Person::players.size(); i++) {
5241 Person::players[i]->wentforweapon = 0;
5245 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
5254 damage -= multiplier * 13;
5255 permanentdamage -= multiplier * 4;
5256 if (isIdle() || isCrouch()) {
5257 permanentdamage -= multiplier * 4;
5263 if (permanentdamage < 0) {
5264 permanentdamage = 0;
5266 if (superpermanentdamage < 0) {
5267 superpermanentdamage = 0;
5269 if (permanentdamage < superpermanentdamage) {
5270 permanentdamage = superpermanentdamage;
5272 if (damage < permanentdamage) {
5273 damage = permanentdamage;
5275 if (dead == 1 && damage < damagetolerance) {
5279 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5280 skeleton.joints[i].velocity = 0;
5283 if (permanentdamage > damagetolerance && dead != 2) {
5286 if (weaponactive != -1) {
5287 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5288 weapons[weaponids[0]].velocity.x += .01;
5291 weaponids[0] = weaponids[num_weapons];
5292 if (weaponstuck == num_weapons) {
5297 for (unsigned i = 0; i < Person::players.size(); i++) {
5298 Person::players[i]->wentforweapon = 0;
5304 if (!dead && creature == wolftype) {
5305 award_bonus(0, Wolfbonus);
5308 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance) {
5309 award_bonus(id, touchofdeath);
5311 if (id != 0 && unconscioustime > .1) {
5319 emit_sound_at(breaksound, coords);
5322 if (skeleton.free == 1) {
5324 pause_sound(whooshsound);
5328 //If knocked over, open hands and close mouth
5329 if (righthandmorphend != 0) {
5330 righthandmorphness = 0;
5332 righthandmorphend = 0;
5333 targetrighthandmorphness = 1;
5335 if (lefthandmorphend != 0) {
5336 lefthandmorphness = 0;
5338 lefthandmorphend = 0;
5339 targetlefthandmorphness = 1;
5341 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
5342 if (headmorphend != 0) {
5346 targetheadmorphness = 1;
5350 skeleton.DoGravity(&scale);
5352 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
5353 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1)) {
5354 award_bonus(id, deepimpact);
5356 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5360 if (!skeleton.joints.empty()) {
5361 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5362 average += skeleton.joints[j].position;
5364 average /= skeleton.joints.size();
5365 coords += average * scale;
5366 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5367 skeleton.joints[j].position -= average;
5369 average /= multiplier;
5373 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5374 velocity += skeleton.joints[i].velocity * scale;
5376 velocity /= skeleton.joints.size();
5378 if (!isnormal(velocity.x) && velocity.x) {
5382 if (findLength(&average) < 10 && dead && skeleton.free) {
5383 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5384 if (skeleton.longdead > 2000) {
5385 if (skeleton.longdead > 6000) {
5387 pause_sound(whooshsound);
5393 if (dead == 2 && bloodloss < damagetolerance) {
5395 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5397 if (bloodtoggle && !bled) {
5398 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5399 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5400 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5401 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5402 float size = .2 * 1.2;
5405 Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5410 if (dead == 2 && bloodloss >= damagetolerance) {
5412 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5413 if (bleeding <= 0) {
5416 if (bloodtoggle && !bled) {
5417 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5418 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5419 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5420 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5424 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5432 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5433 bool canrecover = 1;
5434 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5435 startpoint = coords;
5438 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1) {
5441 if (velocity.y < -30) {
5444 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5445 if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) {
5446 colviewer = startpoint;
5447 coltarget = endpoint;
5448 if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1) {
5458 terrainnormal = jointPos(groin) - jointPos(abdomen);
5459 if (joint(groin).locked && joint(abdomen).locked) {
5460 terrainnormal = jointPos(groin) - jointPos(abdomen);
5461 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5463 if (joint(abdomen).locked && joint(neck).locked) {
5464 terrainnormal = jointPos(abdomen) - jointPos(neck);
5465 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5467 if (joint(groin).locked && joint(neck).locked) {
5468 terrainnormal = jointPos(groin) - jointPos(neck);
5469 middle = (jointPos(groin) + jointPos(neck)) / 2;
5471 Normalise(&terrainnormal);
5473 targetyaw = -asin(0 - terrainnormal.x);
5474 targetyaw *= 360 / 6.28;
5475 if (terrainnormal.z < 0) {
5476 targetyaw = 180 - targetyaw;
5481 animTarget = flipanim;
5482 crouchtogglekeydown = 1;
5487 animCurrent = tempanim;
5491 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5492 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5493 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5498 if (findLength(&average) < 10 && !dead && skeleton.free) {
5499 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5500 if (skeleton.longdead > (damage + 500) * 1.5) {
5502 pause_sound(whooshsound);
5509 terrainnormal = jointPos(groin) - jointPos(abdomen);
5510 if (joint(groin).locked && joint(abdomen).locked) {
5511 terrainnormal = jointPos(groin) - jointPos(abdomen);
5512 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5514 if (joint(abdomen).locked && joint(neck).locked) {
5515 terrainnormal = jointPos(abdomen) - jointPos(neck);
5516 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5518 if (joint(groin).locked && joint(neck).locked) {
5519 terrainnormal = jointPos(groin) - jointPos(neck);
5520 middle = (jointPos(groin) + jointPos(neck)) / 2;
5522 Normalise(&terrainnormal);
5524 targetyaw = -asin(0 - terrainnormal.x);
5525 targetyaw *= 360 / 6.28;
5526 if (terrainnormal.z < 0) {
5527 targetyaw = 180 - targetyaw;
5531 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5533 if (skeleton.forward.y < 0) {
5534 animTarget = getupfrombackanim;
5538 if (skeleton.forward.y > -.3) {
5539 animTarget = getupfromfrontanim;
5547 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5548 animTarget = rollanim;
5549 targetyaw = lookyaw;
5553 if (forwardkeydown) {
5562 if (forwardkeydown) {
5570 if (!leftkeydown && !rightkeydown) {
5578 if (abs(targettilt2) > 50) {
5581 animCurrent = tempanim;
5584 tilt2 = targettilt2;
5586 if (middle.y > 0 && animTarget != rollanim) {
5587 targetoffset.y = middle.y + 1;
5590 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5591 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5592 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5599 if (num_weapons > 0) {
5600 if (weapons[0].getType() == staff) {
5604 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5605 if (velocity.y > -30) {
5607 tempvelocity = velocity;
5608 Normalise(&tempvelocity);
5609 targetyaw = -asin(0 - tempvelocity.x);
5610 targetyaw *= 360 / 6.28;
5611 if (velocity.z < 0) {
5612 targetyaw = 180 - targetyaw;
5617 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5618 animTarget = rollanim;
5621 animTarget = backhandspringanim;
5627 emit_sound_at(movewhooshsound, coords, 128.);
5629 animCurrent = animTarget;
5630 frameCurrent = frameTarget - 1;
5642 if (skeleton.freefall == 0) {
5647 if (aitype != passivetype || skeleton.free == 1) {
5648 if (findLengthfast(&velocity) > .1) {
5649 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5650 if (Object::objects[i]->type == firetype) {
5651 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) {
5653 if (!Object::objects[i]->onfire) {
5654 emit_sound_at(firestartsound, Object::objects[i]->position);
5656 Object::objects[i]->onfire = 1;
5659 if (Object::objects[i]->onfire) {
5665 if (Object::objects[i]->type == bushtype) {
5666 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) {
5668 if (!Object::objects[i]->onfire) {
5669 emit_sound_at(firestartsound, Object::objects[i]->position);
5671 Object::objects[i]->onfire = 1;
5675 if (Object::objects[i]->onfire) {
5679 if (Object::objects[i]->messedwith <= 0) {
5683 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5686 addEnvSound(coords, 4 * findLength(&velocity));
5690 if (environment == grassyenvironment) {
5691 howmany = findLength(&velocity) * 4;
5693 if (environment == snowyenvironment) {
5694 howmany = findLength(&velocity) * 2;
5697 if (environment != desertenvironment) {
5698 for (int j = 0; j < howmany; j++) {
5699 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5700 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5701 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5704 pos.x += float(abs(Random() % 100) - 50) / 200;
5705 pos.y += float(abs(Random() % 100) - 50) / 200;
5706 pos.z += float(abs(Random() % 100) - 50) / 200;
5707 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);
5708 Sprite::setLastSpriteSpecial(1);
5712 howmany = findLength(&velocity) * 4;
5714 if (environment == snowyenvironment) {
5715 for (int j = 0; j < howmany; j++) {
5716 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5717 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5718 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5721 pos.x += float(abs(Random() % 100) - 50) / 200;
5722 pos.y += float(abs(Random() % 100) - 50) / 200;
5723 pos.z += float(abs(Random() % 100) - 50) / 200;
5724 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5725 Sprite::setLastSpriteSpecial(2);
5730 Object::objects[i]->rotx += velocity.x * multiplier * 6;
5731 Object::objects[i]->roty += velocity.z * multiplier * 6;
5732 Object::objects[i]->messedwith = .5;
5736 if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) {
5737 if (Object::objects[i]->pitch == 0) {
5740 tempcoord = coords - Object::objects[i]->position;
5741 tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0);
5742 tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0);
5743 tempcoord += Object::objects[i]->position;
5745 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) {
5746 if (Object::objects[i]->messedwith <= 0) {
5750 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5753 addEnvSound(coords, 4 * findLength(&velocity));
5757 if (environment == grassyenvironment) {
5758 howmany = findLength(&velocity) * 4;
5760 if (environment == snowyenvironment) {
5761 howmany = findLength(&velocity) * 2;
5764 if (environment != desertenvironment) {
5765 for (int j = 0; j < howmany; j++) {
5766 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5767 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5768 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5770 pos += velocity * .1;
5772 pos.x += float(abs(Random() % 100) - 50) / 150;
5773 pos.y += float(abs(Random() % 100) - 50) / 150;
5774 pos.z += float(abs(Random() % 100) - 50) / 150;
5775 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);
5776 Sprite::setLastSpriteSpecial(1);
5780 howmany = findLength(&velocity) * 4;
5782 if (environment == snowyenvironment) {
5783 for (int j = 0; j < howmany; j++) {
5784 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5785 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5786 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5788 pos += velocity * .1;
5790 pos.x += float(abs(Random() % 100) - 50) / 150;
5791 pos.y += float(abs(Random() % 100) - 50) / 150;
5792 pos.z += float(abs(Random() % 100) - 50) / 150;
5793 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5794 Sprite::setLastSpriteSpecial(2);
5799 Object::objects[i]->messedwith = .5;
5806 if (!skeleton.free) {
5809 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype) {
5813 if (aitype != passivetype && victim->skeleton.free && !victim->dead) {
5817 if (Tutorial::active && id != 0) {
5820 if (play && aitype != playercontrolled) {
5821 int whichsound = -1;
5822 if (speechdelay <= 0) {
5823 unsigned int i = abs(Random() % 4);
5825 whichsound = PersonType::types[creature].soundsTalk[i];
5830 if (whichsound != -1) {
5831 emit_sound_at(whichsound, coords);
5835 if (animTarget == staggerbackhighanim) {
5838 if (animTarget == staggerbackhardanim) {
5841 staggerdelay -= multiplier;
5842 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
5845 if (velocity.y < -30 && animTarget == jumpdownanim) {
5848 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5849 animTarget = getIdle();
5853 weaponmissdelay -= multiplier;
5854 highreversaldelay -= multiplier;
5855 lowreversaldelay -= multiplier;
5856 lastcollide -= multiplier;
5857 skiddelay -= multiplier;
5858 if (!isnormal(velocity.x) && velocity.x) {
5861 if (!isnormal(targettilt) && targettilt) {
5864 if (!isnormal(targettilt2) && targettilt2) {
5867 if (!isnormal(targetyaw) && targetyaw) {
5871 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5872 //open hands and close mouth
5873 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5874 righthandmorphness = 0;
5875 righthandmorphend = 0;
5876 targetrighthandmorphness = 1;
5879 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5880 lefthandmorphness = 0;
5881 lefthandmorphend = 0;
5882 targetlefthandmorphness = 1;
5885 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5888 targetheadmorphness = 1;
5892 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) {
5893 //open hands and mouth
5894 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5895 righthandmorphness = 0;
5896 righthandmorphend = 0;
5897 targetrighthandmorphness = 1;
5900 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5901 lefthandmorphness = 0;
5902 lefthandmorphend = 0;
5903 targetlefthandmorphness = 1;
5906 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5909 targetheadmorphness = 1;
5913 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5914 //close hands and mouth
5915 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5916 righthandmorphness = 0;
5917 righthandmorphend = 1;
5918 targetrighthandmorphness = 1;
5921 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5922 lefthandmorphness = 0;
5923 lefthandmorphend = 1;
5924 targetlefthandmorphness = 1;
5927 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5930 targetheadmorphness = 1;
5934 if (animTarget == spinkickanim ||
5935 animTarget == staffspinhitreversalanim ||
5936 animTarget == staffspinhitreversedanim ||
5937 animTarget == staffhitreversalanim ||
5938 animTarget == staffhitreversedanim ||
5939 animTarget == hurtidleanim ||
5940 animTarget == winduppunchanim ||
5941 animTarget == swordslashreversalanim ||
5942 animTarget == swordslashreversedanim ||
5943 animTarget == knifeslashreversalanim ||
5944 animTarget == knifeslashreversedanim ||
5945 animTarget == knifethrowanim ||
5946 animTarget == knifefollowanim ||
5947 animTarget == knifefollowedanim ||
5948 animTarget == killanim ||
5949 animTarget == dropkickanim ||
5950 animTarget == upunchanim ||
5951 animTarget == knifeslashstartanim ||
5952 animTarget == swordslashanim ||
5953 animTarget == staffhitanim ||
5954 animTarget == staffspinhitanim ||
5955 animTarget == staffgroundsmashanim ||
5956 animTarget == spinkickreversalanim ||
5957 animTarget == sweepreversalanim ||
5958 animTarget == lowkickanim ||
5959 animTarget == sweepreversedanim ||
5960 animTarget == rabbitkickreversalanim ||
5961 animTarget == rabbitkickreversedanim ||
5962 animTarget == jumpreversalanim ||
5963 animTarget == jumpreversedanim) {
5964 //close hands and yell
5965 if (righthandmorphend != 1 &&
5966 righthandmorphness == targetrighthandmorphness) {
5967 righthandmorphness = 0;
5968 righthandmorphend = 1;
5969 targetrighthandmorphness = 1;
5972 if (lefthandmorphend != 1 &&
5973 lefthandmorphness == targetlefthandmorphness) {
5974 lefthandmorphness = 0;
5975 lefthandmorphend = 1;
5976 targetlefthandmorphness = 1;
5979 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5982 targetheadmorphness = 1;
5989 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5990 (victim->aitype != searchtype) && (aitype != passivetype) &&
5991 (aitype != searchtype) && (victim->id < Person::players.size())) {
5992 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5996 if (!dead && animTarget != hurtidleanim) {
5997 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5998 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
6001 targetheadmorphness = 1;
6006 if (weaponactive != -1) {
6007 if (weapons[weaponids[weaponactive]].getType() != staff) {
6008 righthandmorphstart = 1;
6009 righthandmorphend = 1;
6011 if (weapons[weaponids[weaponactive]].getType() == staff) {
6012 righthandmorphstart = 2;
6013 righthandmorphend = 2;
6015 targetrighthandmorphness = 1;
6018 terrainnormal = terrain.getNormal(coords.x, coords.z);
6020 if (Animation::animations[animTarget].attack != reversal) {
6021 if (!isnormal(coords.x)) {
6030 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
6031 facing = flatfacing;
6032 ReflectVector(&facing, terrainnormal);
6036 animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
6038 targettilt2 = -facing.y * 20;
6044 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim) {
6047 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6048 flatvelocity = velocity;
6050 flatvelspeed = findLength(&flatvelocity);
6051 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
6052 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
6053 if (velocity.y < 0) {
6056 if (velocity.y < 0) {
6059 if (targettilt > 25) {
6062 if (targettilt < -25) {
6067 if (targettilt2 > 45) {
6070 if (targettilt2 < -45) {
6073 if (abs(tilt2 - targettilt2) < multiplier * 400) {
6074 tilt2 = targettilt2;
6075 } else if (tilt2 > targettilt2) {
6076 tilt2 -= multiplier * 400;
6077 } else if (tilt2 < targettilt2) {
6078 tilt2 += multiplier * 400;
6080 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
6089 if (!isnormal(targettilt) && targettilt) {
6092 if (!isnormal(targettilt2) && targettilt2) {
6097 if (animTarget == rabbittackleanim) {
6098 velocity += facing * multiplier * speed * 700 * scale;
6099 velspeed = findLength(&velocity);
6100 if (velspeed > speed * 65 * scale) {
6101 velocity /= velspeed;
6102 velspeed = speed * 65 * scale;
6103 velocity *= velspeed;
6105 velocity.y += gravity * multiplier * 20;
6106 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6107 velspeed = findLength(&velocity);
6108 velocity = flatfacing * velspeed;
6110 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
6111 if (isRun() || animTarget == rabbitkickanim) {
6112 velocity += facing * multiplier * speed * 700 * scale;
6113 velspeed = findLength(&velocity);
6114 if (velspeed > speed * 45 * scale) {
6115 velocity /= velspeed;
6116 velspeed = speed * 45 * scale;
6117 velocity *= velspeed;
6119 velocity.y += gravity * multiplier * 20;
6120 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6121 velspeed = findLength(&velocity);
6122 if (velspeed < speed * 30 * scale) {
6123 velspeed = speed * 30 * scale;
6125 velocity = flatfacing * velspeed;
6127 } else if (isRun()) {
6128 velocity += facing * multiplier * speed * 700 * scale;
6129 velspeed = findLength(&velocity);
6130 if (creature == rabbittype) {
6131 if (velspeed > speed * 55 * scale) {
6132 velocity /= velspeed;
6133 velspeed = speed * 55 * scale;
6134 velocity *= velspeed;
6137 if (creature == wolftype) {
6138 if (velspeed > speed * 75 * scale) {
6139 velocity /= velspeed;
6140 velspeed = speed * 75 * scale;
6141 velocity *= velspeed;
6144 velocity.y += gravity * multiplier * 20;
6145 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6146 velspeed = findLength(&velocity);
6147 velocity = flatfacing * velspeed;
6150 if (animTarget == rollanim && targetFrame().label != 6) {
6151 velocity += facing * multiplier * speed * 700 * scale;
6152 velspeed = findLength(&velocity);
6153 if (velspeed > speed * 45 * scale) {
6154 velocity /= velspeed;
6155 velspeed = speed * 45 * scale;
6156 velocity *= velspeed;
6158 velocity.y += gravity * multiplier * 20;
6159 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6160 velspeed = findLength(&velocity);
6161 velocity = flatfacing * velspeed;
6164 if (animTarget == sneakanim || animTarget == walkanim) {
6165 velocity += facing * multiplier * speed * 700 * scale;
6166 velspeed = findLength(&velocity);
6167 if (velspeed > speed * 12 * scale) {
6168 velocity /= velspeed;
6169 velspeed = speed * 12 * scale;
6170 velocity *= velspeed;
6172 velocity.y += gravity * multiplier * 20;
6173 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6174 velspeed = findLength(&velocity);
6175 velocity = flatfacing * velspeed;
6178 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
6179 velocity += facing * multiplier * speed * 700 * scale;
6180 velspeed = findLength(&velocity);
6181 if (velspeed > speed * 2 * scale) {
6182 velocity /= velspeed;
6183 velspeed = speed * 2 * scale;
6184 velocity *= velspeed;
6186 velocity.y += gravity * multiplier * 20;
6187 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6188 velspeed = findLength(&velocity);
6189 velocity = flatfacing * velspeed;
6192 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
6193 velocity -= facing * multiplier * speed * 700 * scale;
6194 velspeed = findLength(&velocity);
6195 if (velspeed > speed * 2 * scale) {
6196 velocity /= velspeed;
6197 velspeed = speed * 2 * scale;
6198 velocity *= velspeed;
6200 velocity.y += gravity * multiplier * 20;
6201 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6202 velspeed = findLength(&velocity);
6203 velocity = flatfacing * velspeed * -1;
6206 if (animTarget == fightsidestep) {
6207 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
6208 velspeed = findLength(&velocity);
6209 if (velspeed > speed * 12 * scale) {
6210 velocity /= velspeed;
6211 velspeed = speed * 12 * scale;
6212 velocity *= velspeed;
6214 velocity.y += gravity * multiplier * 20;
6215 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6216 velspeed = findLength(&velocity);
6217 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
6220 if (animTarget == staggerbackhighanim) {
6221 coords -= facing * multiplier * speed * 16 * scale;
6224 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
6225 coords -= facing * multiplier * speed * 20 * scale;
6229 if (animTarget == backhandspringanim) {
6230 //coords-=facing*multiplier*50*scale;
6231 velocity += facing * multiplier * speed * 700 * scale * -1;
6232 velspeed = findLength(&velocity);
6233 if (velspeed > speed * 50 * scale) {
6234 velocity /= velspeed;
6235 velspeed = speed * 50 * scale;
6236 velocity *= velspeed;
6238 velocity.y += gravity * multiplier * 20;
6239 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6240 velspeed = findLength(&velocity);
6241 velocity = flatfacing * velspeed * -1;
6243 if (animTarget == dodgebackanim) {
6244 //coords-=facing*multiplier*50*scale;
6245 velocity += facing * multiplier * speed * 700 * scale * -1;
6246 velspeed = findLength(&velocity);
6247 if (velspeed > speed * 60 * scale) {
6248 velocity /= velspeed;
6249 velspeed = speed * 60 * scale;
6250 velocity *= velspeed;
6252 velocity.y += gravity * multiplier * 20;
6253 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6254 velspeed = findLength(&velocity);
6255 velocity = flatfacing * velspeed * -1;
6258 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6259 velspeed = findLength(&velocity);
6262 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6263 velocity.y += gravity * multiplier;
6266 if (animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6267 coords += velocity * multiplier;
6270 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6271 if (isFlip() && targetFrame().label == 7) {
6275 if (animTarget == jumpupanim) {
6277 animTarget = getIdle();
6284 pause_sound(whooshsound);
6285 OPENAL_SetVolume(channels[whooshsound], 0);
6288 if (animTarget == jumpdownanim || isFlip()) {
6292 animTarget = getLanding();
6293 emit_sound_at(landsound, coords, 128.);
6296 addEnvSound(coords);
6301 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6302 coords.y += gravity * multiplier * 2;
6304 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
6305 coords.y = terrain.getHeight(coords.x, coords.z);
6309 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)) {
6310 velspeed = findLength(&velocity);
6312 if (velspeed < multiplier * 300 * scale) {
6315 velocity -= velocity / velspeed * multiplier * 300 * scale;
6317 if (velspeed > 5 && (isLanding() || isLandhard())) {
6318 skiddingdelay += multiplier;
6319 if (skiddelay <= 0) {
6320 FootLand(leftfoot, .5);
6321 FootLand(rightfoot, .5);
6330 velspeed = findLength(&velocity);
6332 if (velspeed > 5 && (isLanding() || isLandhard())) {
6333 skiddingdelay += multiplier;
6334 if (skiddelay <= 0) {
6335 FootLand(leftfoot, .5);
6336 FootLand(rightfoot, .5);
6344 if (skiddingdelay < 0) {
6345 skiddingdelay += multiplier;
6347 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
6349 if (!onterrain || environment == grassyenvironment) {
6350 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
6352 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
6356 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
6357 terrainnormal = victim->coords - coords;
6358 Normalise(&terrainnormal);
6359 targetyaw = -asin(0 - terrainnormal.x);
6360 targetyaw *= 360 / 6.28;
6361 if (terrainnormal.z < 0) {
6362 targetyaw = 180 - targetyaw;
6364 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
6367 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
6368 targetyaw = victim->targetyaw;
6370 if (animTarget == rabbittacklinganim) {
6371 coords = victim->coords;
6374 skeleton.oldfree = skeleton.free;
6378 midterrain.x = terrain.size * terrain.scale / 2;
6379 midterrain.z = terrain.size * terrain.scale / 2;
6380 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
6382 tempposit = coords - midterrain;
6384 Normalise(&tempposit);
6385 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
6386 coords.x = tempposit.x + midterrain.x;
6387 coords.z = tempposit.z + midterrain.z;
6392 * inverse kinematics helper function
6394 void IKHelper(Person* p, float interp)
6396 XYZ point, change, change2;
6397 float heightleft, heightright;
6399 // TODO: implement localToWorld and worldToLocal
6400 // but keep in mind it won't be the same math if player is ragdolled or something
6401 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
6402 // then comb through code for places where to use it
6404 // point = localToWorld(jointPos(leftfoot))
6405 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
6406 // adjust height of foot
6407 heightleft = terrain.getHeight(point.x, point.z) + .04;
6408 point.y = heightleft;
6409 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
6410 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
6411 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
6412 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
6413 // move ankle along with foot
6414 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
6415 // average knee pos between old and new pos
6416 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
6418 // do same as above for right leg
6419 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
6420 heightright = terrain.getHeight(point.x, point.z) + .04;
6421 point.y = heightright;
6422 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
6423 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
6424 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
6425 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
6426 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
6428 // fix up skeleton now that we've moved body parts?
6429 p->skeleton.DoConstraints(&p->coords, &p->scale);
6436 int Person::DrawSkeleton()
6438 int oldplayerdetail;
6439 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6440 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6450 glAlphaFunc(GL_GREATER, 0.0001);
6452 float terrainheight;
6454 if (!isnormal(yaw)) {
6457 if (!isnormal(tilt)) {
6460 if (!isnormal(tilt2)) {
6463 oldplayerdetail = playerdetail;
6465 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6468 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6471 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6477 if (playerdetail != oldplayerdetail) {
6479 normalsupdatedelay = 0;
6481 static float updatedelaychange;
6482 static float morphness;
6483 static float framemult;
6485 skeleton.FindForwards();
6486 if (howactive == typesittingwall) {
6487 skeleton.specialforward[1] = 0;
6488 skeleton.specialforward[1].z = 1;
6494 static int weaponattachmuscle;
6495 static int weaponrotatemuscle;
6496 static XYZ weaponpoint;
6497 static int start, endthing;
6498 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6499 if (!isSleeping() && !isSitting()) {
6500 // TODO: give these meaningful names
6501 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6502 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard() || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6504 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6506 if (creature == wolftype) {
6511 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6512 IKHelper(this, target);
6513 if (creature == wolftype) {
6514 IKHelper(this, target);
6518 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6519 IKHelper(this, 1 - target);
6520 if (creature == wolftype) {
6521 IKHelper(this, 1 - target);
6526 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())) {
6529 targetheadyaw = -targetyaw;
6530 targetheadpitch = 0;
6531 if (Animation::animations[animTarget].attack == 3) {
6532 targetheadyaw += 180;
6535 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6536 skeleton.drawmodel.vertex[i] = 0;
6537 skeleton.drawmodel.vertex[i].y = 999;
6539 for (int i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6540 skeleton.drawmodellow.vertex[i] = 0;
6541 skeleton.drawmodellow.vertex[i].y = 999;
6543 for (int i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6544 skeleton.drawmodelclothes.vertex[i] = 0;
6545 skeleton.drawmodelclothes.vertex[i].y = 999;
6547 for (unsigned int i = 0; i < skeleton.muscles.size(); i++) {
6548 // convenience renames
6549 const int p1 = skeleton.muscles[i].parent1->label;
6550 const int p2 = skeleton.muscles[i].parent2->label;
6552 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6557 if (p1 == righthand || p2 == righthand) {
6558 morphness = righthandmorphness;
6559 start = righthandmorphstart;
6560 endthing = righthandmorphend;
6562 if (p1 == lefthand || p2 == lefthand) {
6563 morphness = lefthandmorphness;
6564 start = lefthandmorphstart;
6565 endthing = lefthandmorphend;
6567 if (p1 == head || p2 == head) {
6568 morphness = headmorphness;
6569 start = headmorphstart;
6570 endthing = headmorphend;
6572 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6573 morphness = chestmorphness;
6574 start = chestmorphstart;
6575 endthing = chestmorphend;
6577 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6578 morphness = tailmorphness;
6579 start = tailmorphstart;
6580 endthing = tailmorphend;
6583 skeleton.FindRotationMuscle(i, animTarget);
6585 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6586 glMatrixMode(GL_MODELVIEW);
6589 if (!skeleton.free) {
6590 glRotatef(tilt2, 1, 0, 0);
6592 if (!skeleton.free) {
6593 glRotatef(tilt, 0, 0, 1);
6596 glTranslatef(mid.x, mid.y, mid.z);
6598 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6599 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6601 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6602 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6604 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6605 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6607 if (playerdetail || skeleton.free == 3) {
6608 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6609 XYZ& v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6610 XYZ& v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6611 glMatrixMode(GL_MODELVIEW);
6613 if (p1 == abdomen || p2 == abdomen) {
6614 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(1).x,
6615 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(1).y,
6616 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(1).z);
6618 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6619 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(2).x,
6620 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(2).y,
6621 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(2).z);
6623 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6624 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(3).x,
6625 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(3).y,
6626 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(3).z);
6628 if (p1 == head || p2 == head) {
6629 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(0).x,
6630 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(0).y,
6631 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(0).z);
6633 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6634 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6635 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6636 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6640 if (!playerdetail || skeleton.free == 3) {
6641 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6642 XYZ& v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6643 glMatrixMode(GL_MODELVIEW);
6645 if (p1 == abdomen || p2 == abdomen) {
6646 glTranslatef(v0.x * getProportion(1).x,
6647 v0.y * getProportion(1).y,
6648 v0.z * getProportion(1).z);
6650 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6651 glTranslatef(v0.x * getProportion(2).x,
6652 v0.y * getProportion(2).y,
6653 v0.z * getProportion(2).z);
6655 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6656 glTranslatef(v0.x * getProportion(3).x,
6657 v0.y * getProportion(3).y,
6658 v0.z * getProportion(3).z);
6660 if (p1 == head || p2 == head) {
6661 glTranslatef(v0.x * getProportion(0).x,
6662 v0.y * getProportion(0).y,
6663 v0.z * getProportion(0).z);
6666 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6667 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6668 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6669 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6675 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6676 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6678 glMatrixMode(GL_MODELVIEW);
6681 if (!skeleton.free) {
6682 glRotatef(tilt2, 1, 0, 0);
6684 if (!skeleton.free) {
6685 glRotatef(tilt, 0, 0, 1);
6687 glTranslatef(mid.x, mid.y, mid.z);
6688 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6689 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6691 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6692 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6694 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6695 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6697 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6698 XYZ& v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6699 glMatrixMode(GL_MODELVIEW);
6701 if (p1 == abdomen || p2 == abdomen) {
6702 glTranslatef(v0.x * getProportion(1).x,
6703 v0.y * getProportion(1).y,
6704 v0.z * getProportion(1).z);
6706 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6707 glTranslatef(v0.x * getProportion(2).x,
6708 v0.y * getProportion(2).y,
6709 v0.z * getProportion(2).z);
6711 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6712 glTranslatef(v0.x * getProportion(3).x,
6713 v0.y * getProportion(3).y,
6714 v0.z * getProportion(3).z);
6716 if (p1 == head || p2 == head) {
6717 glTranslatef(v0.x * getProportion(0).x,
6718 v0.y * getProportion(0).y,
6719 v0.z * getProportion(0).z);
6721 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6722 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6723 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6724 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6729 updatedelay = 1 + (float)(Random() % 100) / 1000;
6731 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6732 normalsupdatedelay = 1;
6733 if (playerdetail || skeleton.free == 3) {
6734 skeleton.drawmodel.CalculateNormals(0);
6736 if (!playerdetail || skeleton.free == 3) {
6737 skeleton.drawmodellow.CalculateNormals(0);
6739 if (skeleton.clothes) {
6740 skeleton.drawmodelclothes.CalculateNormals(0);
6743 if (playerdetail || skeleton.free == 3) {
6744 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6746 if (!playerdetail || skeleton.free == 3) {
6747 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6749 if (skeleton.clothes) {
6750 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6755 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6756 if (updatedelaychange > -realmultiplier * 30) {
6757 updatedelaychange = -realmultiplier * 30;
6759 if (updatedelaychange > -framemult * 4) {
6760 updatedelaychange = -framemult * 4;
6762 if (skeleton.free == 1) {
6763 updatedelaychange *= 6;
6766 updatedelaychange *= 8;
6768 updatedelay += updatedelaychange;
6770 glMatrixMode(GL_MODELVIEW);
6772 glTranslatef(coords.x, coords.y - .02, coords.z);
6773 if (!skeleton.free) {
6774 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6775 glRotatef(yaw, 0, 1, 0);
6779 glColor4f(.4, 1, .4, 1);
6780 glDisable(GL_LIGHTING);
6781 glDisable(GL_TEXTURE_2D);
6784 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6785 XYZ& v0 = skeleton.drawmodel.vertex[i];
6786 glVertex3f(v0.x, v0.y, v0.z);
6793 for (unsigned int i = 0; i < skeleton.drawmodel.Triangles.size(); i++) {
6794 const XYZ& v0 = skeleton.drawmodel.getTriangleVertex(i, 0);
6795 const XYZ& v1 = skeleton.drawmodel.getTriangleVertex(i, 1);
6796 const XYZ& v2 = skeleton.drawmodel.getTriangleVertex(i, 2);
6797 glVertex3f(v0.x, v0.y, v0.z);
6798 glVertex3f(v1.x, v1.y, v1.z);
6799 glVertex3f(v1.x, v1.y, v1.z);
6800 glVertex3f(v2.x, v2.y, v2.z);
6801 glVertex3f(v2.x, v2.y, v2.z);
6802 glVertex3f(v0.x, v0.y, v0.z);
6809 terrainlight = terrain.getLighting(coords.x, coords.z);
6810 distance = distsq(&viewer, &coords);
6811 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6816 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6817 if (terrainheight < 1) {
6820 if (terrainheight > 1.7) {
6821 terrainheight = 1.7;
6824 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6825 glDisable(GL_BLEND);
6826 glAlphaFunc(GL_GREATER, 0.0001);
6827 glEnable(GL_TEXTURE_2D);
6829 glDisable(GL_TEXTURE_2D);
6830 glColor4f(.7, .35, 0, .5);
6832 glEnable(GL_LIGHTING);
6835 if (Tutorial::active && id != 0) {
6836 glColor4f(.7, .7, .7, 0.6);
6838 glEnable(GL_LIGHTING);
6840 if (canattack && cananger) {
6841 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6842 glDisable(GL_TEXTURE_2D);
6843 glColor4f(1, 0, 0, 0.8);
6846 glMatrixMode(GL_TEXTURE);
6848 glTranslatef(0, -smoketex, 0);
6849 glTranslatef(-smoketex, 0, 0);
6853 if (Tutorial::active && (id != 0)) {
6854 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6856 skeleton.drawmodel.draw();
6860 if (!playerdetail) {
6861 if (Tutorial::active && (id != 0)) {
6862 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6864 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6868 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed)) {
6869 if (Tutorial::active && id != 0) {
6871 glMatrixMode(GL_MODELVIEW);
6872 glEnable(GL_TEXTURE_2D);
6873 glColor4f(.7, .7, .7, 0.6);
6875 glEnable(GL_LIGHTING);
6877 if (canattack && cananger) {
6878 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6879 glDisable(GL_TEXTURE_2D);
6880 glColor4f(1, 0, 0, 0.8);
6883 glMatrixMode(GL_TEXTURE);
6885 glTranslatef(0, -smoketex * .6, 0);
6886 glTranslatef(smoketex * .6, 0, 0);
6889 if (Tutorial::active && (id != 0)) {
6890 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6892 skeleton.drawmodel.draw();
6896 if (!playerdetail) {
6897 if (Tutorial::active && (id != 0)) {
6898 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6900 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6906 if (Tutorial::active && id != 0) {
6908 glMatrixMode(GL_MODELVIEW);
6909 glEnable(GL_TEXTURE_2D);
6911 if (skeleton.clothes) {
6915 skeleton.drawmodelclothes.draw();
6918 skeleton.drawmodelclothes.drawimmediate();
6925 if (num_weapons > 0) {
6926 for (k = 0; k < num_weapons; k++) {
6927 int i = weaponids[k];
6928 if (weaponactive == k) {
6929 if (weapons[i].getType() != staff) {
6930 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6931 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6932 weaponattachmuscle = j;
6935 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6936 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) {
6937 weaponrotatemuscle = j;
6940 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6941 if (creature == wolftype) {
6942 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6945 if (weapons[i].getType() == staff) {
6946 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6947 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6948 weaponattachmuscle = j;
6951 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6952 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) {
6953 weaponrotatemuscle = j;
6956 //weaponpoint=jointPos(rightwrist);
6957 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6958 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6959 XYZ tempnormthing, vec1, vec2;
6960 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6961 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6962 CrossProduct(&vec1, &vec2, &tempnormthing);
6963 Normalise(&tempnormthing);
6964 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim) {
6965 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6969 if (weaponactive != k && weaponstuck != k) {
6970 if (weapons[i].getType() == knife) {
6971 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6973 if (weapons[i].getType() == sword) {
6974 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6976 if (weapons[i].getType() == staff) {
6977 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6979 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6980 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) {
6981 weaponrotatemuscle = j;
6985 if (weaponstuck == k) {
6986 if (weaponstuckwhere == 0) {
6987 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6989 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6991 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6992 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) {
6993 weaponrotatemuscle = j;
6997 if (skeleton.free) {
6998 weapons[i].position = weaponpoint * scale + coords;
6999 weapons[i].bigrotation = 0;
7000 weapons[i].bigtilt = 0;
7001 weapons[i].bigtilt2 = 0;
7003 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;
7004 weapons[i].bigrotation = yaw;
7005 weapons[i].bigtilt = tilt;
7006 weapons[i].bigtilt2 = tilt2;
7008 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
7009 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
7010 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
7011 if (weaponactive == k) {
7012 if (weapons[i].getType() == knife) {
7013 weapons[i].smallrotation = 180;
7014 weapons[i].smallrotation2 = 0;
7015 if (isCrouch() || wasCrouch()) {
7016 weapons[i].smallrotation2 = 20;
7018 if (animTarget == hurtidleanim) {
7019 weapons[i].smallrotation2 = 50;
7021 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
7022 XYZ temppoint1, temppoint2;
7025 temppoint1 = jointPos(righthand);
7026 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7027 distance = findDistance(&temppoint1, &temppoint2);
7028 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7029 weapons[i].rotation2 *= 360 / 6.28;
7032 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7033 weapons[i].rotation1 *= 360 / 6.28;
7034 weapons[i].rotation3 = 0;
7035 weapons[i].smallrotation = -90;
7036 weapons[i].smallrotation2 = 0;
7037 if (temppoint1.x > temppoint2.x) {
7038 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7041 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
7042 XYZ temppoint1, temppoint2;
7045 temppoint1 = jointPos(righthand);
7046 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7047 distance = findDistance(&temppoint1, &temppoint2);
7048 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7049 weapons[i].rotation2 *= 360 / 6.28;
7052 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7053 weapons[i].rotation1 *= 360 / 6.28;
7054 weapons[i].rotation3 = 0;
7055 weapons[i].smallrotation = 90;
7056 weapons[i].smallrotation2 = 0;
7057 if (temppoint1.x > temppoint2.x) {
7058 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7061 if (animTarget == knifethrowanim) {
7062 weapons[i].smallrotation = 90;
7063 //weapons[i].smallrotation2=-90;
7064 weapons[i].smallrotation2 = 0;
7065 weapons[i].rotation1 = 0;
7066 weapons[i].rotation2 = 0;
7067 weapons[i].rotation3 = 0;
7069 if (animTarget == knifesneakattackanim && frameTarget < 5) {
7070 weapons[i].smallrotation = -90;
7071 weapons[i].rotation1 = 0;
7072 weapons[i].rotation2 = 0;
7073 weapons[i].rotation3 = 0;
7076 if (weapons[i].getType() == sword) {
7077 weapons[i].smallrotation = 0;
7078 weapons[i].smallrotation2 = 0;
7079 if (animTarget == knifethrowanim) {
7080 weapons[i].smallrotation = -90;
7081 weapons[i].smallrotation2 = 0;
7082 weapons[i].rotation1 = 0;
7083 weapons[i].rotation2 = 0;
7084 weapons[i].rotation3 = 0;
7086 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)) {
7087 XYZ temppoint1, temppoint2;
7090 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
7091 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7092 distance = findDistance(&temppoint1, &temppoint2);
7093 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7094 weapons[i].rotation2 *= 360 / 6.28;
7097 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7098 weapons[i].rotation1 *= 360 / 6.28;
7099 weapons[i].rotation3 = 0;
7100 weapons[i].smallrotation = 90;
7101 weapons[i].smallrotation2 = 0;
7102 if (temppoint1.x > temppoint2.x) {
7103 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7107 if (weapons[i].getType() == staff) {
7108 weapons[i].smallrotation = 100;
7109 weapons[i].smallrotation2 = 0;
7110 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
7111 XYZ temppoint1, temppoint2;
7114 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
7115 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7116 distance = findDistance(&temppoint1, &temppoint2);
7117 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7118 weapons[i].rotation2 *= 360 / 6.28;
7121 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7122 weapons[i].rotation1 *= 360 / 6.28;
7123 weapons[i].rotation3 = 0;
7124 weapons[i].smallrotation = 90;
7125 weapons[i].smallrotation2 = 0;
7126 if (temppoint1.x > temppoint2.x) {
7127 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7132 if (weaponactive != k && weaponstuck != k) {
7133 if (weapons[i].getType() == knife) {
7134 weapons[i].smallrotation = -70;
7135 weapons[i].smallrotation2 = 10;
7137 if (weapons[i].getType() == sword) {
7138 weapons[i].smallrotation = -100;
7139 weapons[i].smallrotation2 = -8;
7141 if (weapons[i].getType() == staff) {
7142 weapons[i].smallrotation = -100;
7143 weapons[i].smallrotation2 = -8;
7146 if (weaponstuck == k) {
7147 if (weaponstuckwhere == 0) {
7148 weapons[i].smallrotation = 180;
7150 weapons[i].smallrotation = 0;
7152 weapons[i].smallrotation2 = 10;
7159 if (skeleton.free) {
7162 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump()) {
7165 if (animCurrent != animTarget) {
7168 if (skeleton.free == 2) {
7177 int Person::SphereCheck(XYZ* p1, float radius, XYZ* p, XYZ* move, float* rotate, Model* model)
7179 static float distance;
7180 static float olddistance;
7181 static int intersecting;
7182 static int firstintersecting;
7185 static XYZ start, end;
7186 static float slopethreshold = -.4;
7188 firstintersecting = -1;
7192 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius) {
7196 *p1 = DoRotation(*p1, 0, -*rotate, 0);
7198 for (int i = 0; i < 4; i++) {
7199 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7200 if (model->Triangles[j].facenormal.y <= slopethreshold) {
7202 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)));
7203 if (distance < radius) {
7204 point = *p1 - model->Triangles[j].facenormal * distance;
7205 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]])) {
7208 if (!intersecting) {
7209 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7210 &model->vertex[model->Triangles[j].vertex[1]],
7213 if (!intersecting) {
7214 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
7215 &model->vertex[model->Triangles[j].vertex[2]],
7218 if (!intersecting) {
7219 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7220 &model->vertex[model->Triangles[j].vertex[2]],
7224 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7228 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)) {
7229 p1->y = point.y + radius;
7230 if ((animTarget == jumpdownanim || isFlip())) {
7231 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4)) {
7235 if (animTarget == jumpupanim) {
7237 animTarget = getIdle();
7244 pause_sound(whooshsound);
7245 OPENAL_SetVolume(channels[whooshsound], 0);
7248 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
7252 animTarget = getLanding();
7253 emit_sound_at(landsound, coords, 128.);
7256 addEnvSound(coords);
7263 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7264 olddistance = distance;
7265 firstintersecting = j;
7270 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7271 if (model->Triangles[j].facenormal.y > slopethreshold) {
7274 start.y -= radius / 4;
7275 XYZ& v0 = model->vertex[model->Triangles[j].vertex[0]];
7276 XYZ& v1 = model->vertex[model->Triangles[j].vertex[1]];
7277 XYZ& v2 = model->vertex[model->Triangles[j].vertex[2]];
7278 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)));
7279 if (distance < radius * .5) {
7280 point = start - model->Triangles[j].facenormal * distance;
7281 if (PointInTriangle(&point, model->Triangles[j].facenormal, &v0, &v1, &v2)) {
7284 if (!intersecting) {
7285 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
7287 if (!intersecting) {
7288 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7290 if (!intersecting) {
7291 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7294 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7295 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
7297 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;
7298 if (findLengthfast(&start) < findLengthfast(&velocity)) {
7302 *p1 += model->Triangles[j].facenormal * (distance - radius * .5);
7305 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7306 olddistance = distance;
7307 firstintersecting = j;
7314 *p = DoRotation(*p, 0, *rotate, 0);
7318 *p1 = DoRotation(*p1, 0, *rotate, 0);
7321 return firstintersecting;
7324 int findPathDist(int start, int end)
7329 unsigned int smallestcount = 1000;
7330 for (char i = 0; i < 50; i++) {
7331 unsigned int count = 0;
7336 while (last != end && count < 30) {
7338 for (int j = 0; j < Game::numpathpoints; j++) {
7339 if (j != last && j != last2 && j != last3 && j != last4) {
7341 if (Game::numpathpointconnect[j]) {
7342 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7343 if (Game::pathpointconnect[j][k] == last) {
7349 if (Game::numpathpointconnect[last]) {
7350 for (int k = 0; k < Game::numpathpointconnect[last]; k++) {
7351 if (Game::pathpointconnect[last][k] == j) {
7358 if (closest == -1 || Random() % 2 == 0) {
7370 if (count < smallestcount) {
7371 smallestcount = count;
7374 return smallestcount;
7377 void Person::takeWeapon(int weaponId)
7380 weapons[weaponId].owner = id;
7381 if (num_weapons > 0) {
7382 weaponids[num_weapons] = weaponids[0];
7385 weaponids[0] = weaponId;
7388 void Person::addClothes()
7390 if (numclothes > 0) {
7391 for (int i = 0; i < numclothes; i++) {
7398 bool Person::addClothes(const int& clothesId)
7401 const std::string fileName = clothes[clothesId];
7403 GLubyte* array = &skeleton.skinText[0];
7407 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
7412 float tintr = clothestintr[clothesId];
7413 float tintg = clothestintg[clothesId];
7414 float tintb = clothestintb[clothesId];
7436 int bytesPerPixel = texture.bpp / 8;
7440 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
7441 if (bytesPerPixel == 3) {
7443 } else if ((i + 1) % 4 == 0) {
7444 alphanum = texture.data[i];
7446 if ((i + 1) % 4 || bytesPerPixel == 3) {
7448 texture.data[i] *= tintr;
7451 texture.data[i] *= tintg;
7454 texture.data[i] *= tintb;
7456 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
7468 if (aitype != playercontrolled && !Dialog::inDialog()) {
7470 //disable movement in editor
7471 if (Game::editorenabled) {
7476 if (distsqflat(&Person::players[0]->coords, &coords) < 30 &&
7477 Person::players[0]->coords.y > coords.y + 2 &&
7478 !Person::players[0]->onterrain) {
7483 if (aitype == pathfindtype) {
7484 if (finalpathfindpoint == -1) {
7485 float closestdistance;
7486 float tempdist = 0.0f;
7490 closestdistance = -1;
7491 for (int j = 0; j < Game::numpathpoints; j++) {
7492 if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) {
7493 closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]);
7495 finaltarget = Game::pathpoint[j];
7498 finalpathfindpoint = closest;
7499 for (int j = 0; j < Game::numpathpoints; j++) {
7500 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7501 DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7502 if (sq(tempdist) < closestdistance) {
7503 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7504 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7505 closestdistance = sq(tempdist);
7507 finaltarget = colpoint;
7512 finalpathfindpoint = closest;
7514 if (targetpathfindpoint == -1) {
7515 float closestdistance;
7516 float tempdist = 0.0f;
7520 closestdistance = -1;
7521 if (lastpathfindpoint == -1) {
7522 for (int j = 0; j < Game::numpathpoints; j++) {
7523 if (j != lastpathfindpoint) {
7524 if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) {
7525 closestdistance = distsq(&coords, &Game::pathpoint[j]);
7530 targetpathfindpoint = closest;
7531 for (int j = 0; j < Game::numpathpoints; j++) {
7532 if (j != lastpathfindpoint) {
7533 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7534 DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7535 if (sq(tempdist) < closestdistance) {
7536 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7537 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7538 closestdistance = sq(tempdist);
7545 targetpathfindpoint = closest;
7547 for (int j = 0; j < Game::numpathpoints; j++) {
7548 if (j != lastpathfindpoint &&
7549 j != lastpathfindpoint2 &&
7550 j != lastpathfindpoint3 &&
7551 j != lastpathfindpoint4) {
7553 if (Game::numpathpointconnect[j]) {
7554 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7555 if (Game::pathpointconnect[j][k] == lastpathfindpoint) {
7561 if (Game::numpathpointconnect[lastpathfindpoint]) {
7562 for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++) {
7563 if (Game::pathpointconnect[lastpathfindpoint][k] == j) {
7570 tempdist = findPathDist(j, finalpathfindpoint);
7571 if (closest == -1 || tempdist < closestdistance) {
7572 closestdistance = tempdist;
7578 targetpathfindpoint = closest;
7581 losupdatedelay -= multiplier;
7583 targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]);
7584 lookyaw = targetyaw;
7586 //reached target point
7587 if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) {
7588 lastpathfindpoint4 = lastpathfindpoint3;
7589 lastpathfindpoint3 = lastpathfindpoint2;
7590 lastpathfindpoint2 = lastpathfindpoint;
7591 lastpathfindpoint = targetpathfindpoint;
7592 if (lastpathfindpoint2 == -1) {
7593 lastpathfindpoint2 = lastpathfindpoint;
7595 if (lastpathfindpoint3 == -1) {
7596 lastpathfindpoint3 = lastpathfindpoint2;
7598 if (lastpathfindpoint4 == -1) {
7599 lastpathfindpoint4 = lastpathfindpoint3;
7601 targetpathfindpoint = -1;
7603 if (distsqflat(&coords, &finalfinaltarget) <
7604 distsqflat(&coords, &finaltarget) ||
7605 distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) ||
7606 lastpathfindpoint == finalpathfindpoint) {
7607 aitype = passivetype;
7618 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7619 targetyaw += 90 * (whichdirection * 2 - 1);
7622 if (collided < 1 || animTarget != jumpupanim) {
7625 if ((collided > .8 && jumppower >= 5)) {
7629 if ((!Tutorial::active || cananger) &&
7631 !Person::players[0]->dead &&
7632 distsq(&coords, &Person::players[0]->coords) < 400 &&
7634 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7635 Animation::animations[Person::players[0]->animTarget].height != lowheight &&
7636 !Game::editorenabled &&
7637 (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain)) {
7638 aitype = attacktypecutoff;
7640 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7641 Animation::animations[Person::players[0]->animTarget].height == highheight &&
7642 !Game::editorenabled) {
7643 aitype = attacktypecutoff;
7646 if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7647 losupdatedelay = .2;
7648 for (unsigned j = 0; j < Person::players.size(); j++) {
7649 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7650 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7651 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7652 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7653 if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain) {
7654 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) ||
7655 (Person::players[j]->animTarget == hanganim &&
7656 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7657 aitype = searchtype;
7659 lastseen = Person::players[j]->coords;
7670 if (aitype == attacktypecutoff && Game::musictype != 2) {
7671 if (creature != wolftype) {
7678 if (aitype != passivetype && Game::leveltime > .5) {
7679 howactive = typeactive;
7682 if (aitype == passivetype) {
7683 aiupdatedelay -= multiplier;
7684 losupdatedelay -= multiplier;
7685 lastseentime += multiplier;
7686 pausetime -= multiplier;
7687 if (lastseentime > 1) {
7691 if (aiupdatedelay < 0) {
7692 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7693 targetyaw = roughDirectionTo(coords, waypoints[waypoint]);
7694 lookyaw = targetyaw;
7695 aiupdatedelay = .05;
7697 if (distsqflat(&coords, &waypoints[waypoint]) < 1) {
7698 if (waypointtype[waypoint] == wppause) {
7702 if (waypoint > numwaypoints - 1) {
7708 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7720 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7721 if (!avoidsomething) {
7722 targetyaw += 90 * (whichdirection * 2 - 1);
7724 XYZ leftpos, rightpos;
7725 float leftdist, rightdist;
7726 leftpos = coords + DoRotation(facing, 0, 90, 0);
7727 rightpos = coords - DoRotation(facing, 0, 90, 0);
7728 leftdist = distsq(&leftpos, &avoidwhere);
7729 rightdist = distsq(&rightpos, &avoidwhere);
7730 if (leftdist < rightdist) {
7738 if (collided < 1 || animTarget != jumpupanim) {
7741 if ((collided > .8 && jumppower >= 5)) {
7746 if (!Game::editorenabled) {
7747 if (howactive <= typesleeping) {
7748 if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile) {
7749 for (int j = 0; j < numenvsounds; j++) {
7750 float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
7751 if (vol > 0 && distsq(&coords, &envsound[j]) < 2 * (vol + vol * (creature == rabbittype) * 3)) {
7752 aitype = attacktypecutoff;
7758 if (aitype != passivetype) {
7759 if (howactive == typesleeping) {
7760 setTargetAnimation(getupfromfrontanim);
7762 howactive = typeactive;
7766 if (howactive < typesleeping &&
7767 ((!Tutorial::active || cananger) && hostile) &&
7768 !Person::players[0]->dead &&
7769 distsq(&coords, &Person::players[0]->coords) < 400 &&
7771 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7772 Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled) {
7773 aitype = attacktypecutoff;
7775 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7776 Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled) {
7777 aitype = attacktypecutoff;
7781 if (creature == wolftype) {
7783 for (unsigned j = 0; j < Person::players.size(); j++) {
7784 if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
7785 float smelldistance = 50;
7786 if (j == 0 && Person::players[j]->num_weapons > 0) {
7787 if (weapons[Person::players[j]->weaponids[0]].bloody) {
7788 smelldistance = 100;
7790 if (Person::players[j]->num_weapons == 2) {
7791 if (weapons[Person::players[j]->weaponids[1]].bloody) {
7792 smelldistance = 100;
7797 smelldistance = 100;
7799 windsmell = windvector;
7800 Normalise(&windsmell);
7801 windsmell = windsmell * 2 + Person::players[j]->coords;
7802 if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled) {
7803 aitype = attacktypecutoff;
7809 if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7810 losupdatedelay = .2;
7811 for (unsigned j = 0; j < Person::players.size(); j++) {
7812 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7813 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7814 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7815 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7816 if ((-1 == Object::checkcollide(
7817 DoRotation(jointPos(head), 0, yaw, 0) *
7820 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0) *
7821 Person::players[j]->scale +
7822 Person::players[j]->coords) &&
7823 !Person::players[j]->isWallJump()) ||
7824 (Person::players[j]->animTarget == hanganim &&
7825 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7827 if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight) {
7836 if (lastseentime <= 0) {
7837 aitype = searchtype;
7839 lastseen = Person::players[j]->coords;
7847 if (aitype == attacktypecutoff && Game::musictype != 2) {
7848 if (creature != wolftype) {
7852 if (creature == wolftype) {
7862 if (aitype == searchtype) {
7863 aiupdatedelay -= multiplier;
7864 losupdatedelay -= multiplier;
7866 lastseentime -= multiplier;
7868 lastchecktime -= multiplier;
7870 if (isRun() && !onground) {
7871 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7872 XYZ test2 = coords + facing;
7874 XYZ test = coords + facing;
7876 j = Object::checkcollide(test2, test, laststanding);
7878 j = Object::checkcollide(test2, test);
7882 setTargetAnimation(getStop());
7885 //aitype=passivetype;
7886 aitype = pathfindtype;
7887 finalfinaltarget = waypoints[waypoint];
7888 finalpathfindpoint = -1;
7889 targetpathfindpoint = -1;
7890 lastpathfindpoint = -1;
7891 lastpathfindpoint2 = -1;
7892 lastpathfindpoint3 = -1;
7893 lastpathfindpoint4 = -1;
7899 //check out last seen location
7900 if (aiupdatedelay < 0) {
7901 targetyaw = roughDirectionTo(coords, lastseen);
7902 lookyaw = targetyaw;
7903 aiupdatedelay = .05;
7906 if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) {
7909 lastseen.x += (float(Random() % 100) - 50) / 25;
7910 lastseen.z += (float(Random() % 100) - 50) / 25;
7921 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7922 if (!avoidsomething) {
7923 targetyaw += 90 * (whichdirection * 2 - 1);
7925 XYZ leftpos, rightpos;
7926 float leftdist, rightdist;
7927 leftpos = coords + DoRotation(facing, 0, 90, 0);
7928 rightpos = coords - DoRotation(facing, 0, 90, 0);
7929 leftdist = distsq(&leftpos, &avoidwhere);
7930 rightdist = distsq(&rightpos, &avoidwhere);
7931 if (leftdist < rightdist) {
7939 if (collided < 1 || animTarget != jumpupanim) {
7942 if ((collided > .8 && jumppower >= 5)) {
7946 if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile)) {
7947 for (int k = 0; k < numenvsounds; k++) {
7948 if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) {
7949 aitype = attacktypecutoff;
7954 if (!Person::players[0]->dead &&
7955 losupdatedelay < 0 &&
7956 !Game::editorenabled &&
7958 ((!Tutorial::active || cananger) && hostile)) {
7959 losupdatedelay = .2;
7960 if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) {
7961 aitype = attacktypecutoff;
7964 if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight) {
7965 //TODO: factor out canSeePlayer()
7966 if (distsq(&coords, &Person::players[0]->coords) < 400) {
7967 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
7968 if ((Object::checkcollide(
7969 DoRotation(jointPos(head), 0, yaw, 0) *
7972 DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0) *
7973 Person::players[0]->scale +
7974 Person::players[0]->coords) == -1) ||
7975 (Person::players[0]->animTarget == hanganim && normaldotproduct(Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) {
7976 /* //TODO: changed j to 0 on a whim, make sure this is correct
7977 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
7978 Person::players[j]->facing,coords-Person::players[j]->coords)<0)
7980 aitype = attacktypecutoff;
7988 if (lastseentime < 0) {
7989 //aitype=passivetype;
7991 aitype = pathfindtype;
7992 finalfinaltarget = waypoints[waypoint];
7993 finalpathfindpoint = -1;
7994 targetpathfindpoint = -1;
7995 lastpathfindpoint = -1;
7996 lastpathfindpoint2 = -1;
7997 lastpathfindpoint3 = -1;
7998 lastpathfindpoint4 = -1;
8002 if (aitype != gethelptype) {
8006 //get help from buddies
8007 if (aitype == gethelptype) {
8008 runninghowlong += multiplier;
8009 aiupdatedelay -= multiplier;
8011 if (aiupdatedelay < 0 || ally == 0) {
8015 //TODO: factor out closest search somehow
8018 float closestdist = -1;
8019 for (unsigned k = 0; k < Person::players.size(); k++) {
8020 if ((k != id) && (k != 0) && !Person::players[k]->dead &&
8021 (Person::players[k]->howactive < typedead1) &&
8022 !Person::players[k]->skeleton.free &&
8023 (Person::players[k]->aitype == passivetype)) {
8024 float distance = distsq(&coords, &Person::players[k]->coords);
8025 if (closestdist == -1 || distance < closestdist) {
8026 closestdist = distance;
8031 if (closest != -1) {
8036 lastseen = Person::players[0]->coords;
8042 XYZ facing = coords;
8043 XYZ flatfacing = Person::players[ally]->coords;
8044 facing.y += jointPos(head).y * scale;
8045 flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale;
8046 if (-1 != Object::checkcollide(facing, flatfacing)) {
8050 //no available ally, run back to player
8052 Person::players[ally]->skeleton.free ||
8053 Person::players[ally]->aitype != passivetype ||
8054 lastseentime <= 0) {
8055 aitype = searchtype;
8061 targetyaw = roughDirectionTo(coords, Person::players[ally]->coords);
8062 lookyaw = targetyaw;
8063 aiupdatedelay = .05;
8066 if (distsqflat(&coords, &Person::players[ally]->coords) < 3) {
8067 aitype = searchtype;
8069 Person::players[ally]->aitype = searchtype;
8070 if (Person::players[ally]->lastseentime < lastseentime) {
8071 Person::players[ally]->lastseen = lastseen;
8072 Person::players[ally]->lastseentime = lastseentime;
8073 Person::players[ally]->lastchecktime = lastchecktime;
8077 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8078 if (!avoidsomething) {
8079 targetyaw += 90 * (whichdirection * 2 - 1);
8081 XYZ leftpos, rightpos;
8082 float leftdist, rightdist;
8083 leftpos = coords + DoRotation(facing, 0, 90, 0);
8084 rightpos = coords - DoRotation(facing, 0, 90, 0);
8085 leftdist = distsq(&leftpos, &avoidwhere);
8086 rightdist = distsq(&rightpos, &avoidwhere);
8087 if (leftdist < rightdist) {
8102 if (collided < 1 || animTarget != jumpupanim) {
8105 if (collided > .8 && jumppower >= 5) {
8110 //retreiving a weapon on the ground
8111 if (aitype == getweapontype) {
8112 aiupdatedelay -= multiplier;
8113 lastchecktime -= multiplier;
8115 if (aiupdatedelay < 0) {
8121 float closestdist = -1;
8122 for (unsigned k = 0; k < weapons.size(); k++) {
8123 if (weapons[k].owner == -1) {
8124 float distance = distsq(&coords, &weapons[k].position);
8125 if (closestdist == -1 || distance < closestdist) {
8126 closestdist = distance;
8131 if (closest != -1) {
8140 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile)) {
8141 if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) {
8142 aitype = attacktypecutoff;
8146 if (!Person::players[0]->dead) {
8148 if (weapons[ally].owner != -1 ||
8149 distsq(&coords, &weapons[ally].position) > 16) {
8150 aitype = attacktypecutoff;
8153 //TODO: factor these out as moveToward()
8154 targetyaw = roughDirectionTo(coords, weapons[ally].position);
8155 lookyaw = targetyaw;
8156 aiupdatedelay = .05;
8159 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8160 if (!avoidsomething) {
8161 targetyaw += 90 * (whichdirection * 2 - 1);
8163 XYZ leftpos, rightpos;
8164 float leftdist, rightdist;
8165 leftpos = coords + DoRotation(facing, 0, 90, 0);
8166 rightpos = coords - DoRotation(facing, 0, 90, 0);
8167 leftdist = distsq(&leftpos, &avoidwhere);
8168 rightdist = distsq(&rightpos, &avoidwhere);
8169 if (leftdist < rightdist) {
8185 if (animTarget != crouchremoveknifeanim &&
8186 animTarget != removeknifeanim) {
8187 throwtogglekeydown = 0;
8191 if (collided < 1 || animTarget != jumpupanim) {
8194 if ((collided > .8 && jumppower >= 5)) {
8199 if (aitype == attacktypecutoff) {
8200 aiupdatedelay -= multiplier;
8201 //dodge or reverse rabbit kicks, knife throws, flips
8202 if (damage < damagetolerance * 2 / 3) {
8203 if ((Person::players[0]->animTarget == rabbitkickanim ||
8204 Person::players[0]->animTarget == knifethrowanim ||
8205 (Person::players[0]->isFlip() &&
8206 normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) &&
8207 !Person::players[0]->skeleton.free &&
8208 (aiupdatedelay < .1)) {
8213 if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
8214 if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
8215 if (isIdle() || isCrouch() || isRun() || isFlip()) {
8216 if (abs(Random() % 2) == 0) {
8217 setTargetAnimation(backhandspringanim);
8219 setTargetAnimation(rollanim);
8221 targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
8224 if (animTarget == jumpupanim || animTarget == jumpdownanim) {
8225 setTargetAnimation(flipanim);
8230 aiupdatedelay = .02;
8233 //get confused by flips
8234 if (Person::players[0]->isFlip() &&
8235 !Person::players[0]->skeleton.free &&
8236 Person::players[0]->animTarget != walljumprightkickanim &&
8237 Person::players[0]->animTarget != walljumpleftkickanim) {
8238 if (distsq(&Person::players[0]->coords, &coords) < 25) {
8239 if ((1 - damage / damagetolerance) > .5) {
8244 //go for weapon on the ground
8245 if (wentforweapon < 3) {
8246 for (unsigned k = 0; k < weapons.size(); k++) {
8247 if (creature != wolftype) {
8248 if (num_weapons == 0 &&
8249 weapons[k].owner == -1 &&
8250 weapons[k].velocity.x == 0 &&
8251 weapons[k].velocity.z == 0 &&
8252 weapons[k].velocity.y == 0) {
8253 if (distsq(&coords, &weapons[k].position) < 16) {
8256 aitype = getweapontype;
8263 //dodge/reverse walljump kicks
8264 if (damage < damagetolerance / 2) {
8265 if (Animation::animations[animTarget].height != highheight) {
8266 if (damage < damagetolerance * .5 &&
8267 ((Person::players[0]->animTarget == walljumprightkickanim ||
8268 Person::players[0]->animTarget == walljumpleftkickanim) &&
8269 ((aiupdatedelay < .15 &&
8271 (aiupdatedelay < .08 &&
8272 difficulty != 2)))) {
8277 //walked off a ledge (?)
8278 if (isRun() && !onground) {
8279 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
8280 XYZ test2 = coords + facing;
8282 XYZ test = coords + facing;
8284 j = Object::checkcollide(test2, test, laststanding);
8286 j = Object::checkcollide(test2, test);
8290 setTargetAnimation(getStop());
8293 aitype = pathfindtype;
8294 finalfinaltarget = waypoints[waypoint];
8295 finalpathfindpoint = -1;
8296 targetpathfindpoint = -1;
8297 lastpathfindpoint = -1;
8298 lastpathfindpoint2 = -1;
8299 lastpathfindpoint3 = -1;
8300 lastpathfindpoint4 = -1;
8306 //lose sight of player in the air (?)
8307 if (Person::players[0]->coords.y > coords.y + 5 &&
8308 Animation::animations[Person::players[0]->animTarget].height != highheight &&
8309 !Person::players[0]->onterrain) {
8310 aitype = pathfindtype;
8311 finalfinaltarget = waypoints[waypoint];
8312 finalpathfindpoint = -1;
8313 targetpathfindpoint = -1;
8314 lastpathfindpoint = -1;
8315 lastpathfindpoint2 = -1;
8316 lastpathfindpoint3 = -1;
8317 lastpathfindpoint4 = -1;
8319 //it's time to think (?)
8320 if (aiupdatedelay < 0 &&
8321 !Animation::animations[animTarget].attack &&
8322 animTarget != staggerbackhighanim &&
8323 animTarget != staggerbackhardanim &&
8324 animTarget != backhandspringanim &&
8325 animTarget != dodgebackanim) {
8327 if (weaponactive == -1 && num_weapons > 0) {
8328 drawkeydown = Random() % 2;
8332 rabbitkickenabled = Random() % 2;
8334 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
8335 XYZ targetpoint = Person::players[0]->coords;
8336 float vellength = findLength(&velocity);
8337 if (vellength != 0 &&
8338 distsq(&Person::players[0]->coords, &coords) < distsq(&rotatetarget, &coords)) {
8339 targetpoint += Person::players[0]->velocity *
8340 findDistance(&Person::players[0]->coords, &coords) / vellength;
8342 targetyaw = roughDirectionTo(coords, targetpoint);
8343 lookyaw = targetyaw;
8344 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
8346 if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1)) {
8348 } else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
8349 distsq(&coords, &Person::players[0]->coords) < 9) &&
8350 Person::players[0]->weaponactive != -1) {
8352 } else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0)) {
8357 //chill out around the corpse
8358 if (Person::players[0]->dead) {
8360 if (Random() % 10 == 0) {
8363 if (Random() % 100 == 0) {
8364 aitype = pathfindtype;
8365 finalfinaltarget = waypoints[waypoint];
8366 finalpathfindpoint = -1;
8367 targetpathfindpoint = -1;
8368 lastpathfindpoint = -1;
8369 lastpathfindpoint2 = -1;
8370 lastpathfindpoint3 = -1;
8371 lastpathfindpoint4 = -1;
8380 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8381 targetyaw += 90 * (whichdirection * 2 - 1);
8384 if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype) {
8389 if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7) {
8394 if (aitype != playercontrolled &&
8399 for (unsigned j = 0; j < Person::players.size(); j++) {
8400 if (j != id && !Person::players[j]->skeleton.free &&
8401 Person::players[j]->hasvictim &&
8402 (Tutorial::active && reversaltrain ||
8403 Random() % 2 == 0 && difficulty == 2 ||
8404 Random() % 4 == 0 && difficulty == 1 ||
8405 Random() % 8 == 0 && difficulty == 0 ||
8406 Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
8407 Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
8408 (Random() % 2 == 0 || difficulty == 2) ||
8409 (isIdle() || isRun()) &&
8410 Person::players[j]->weaponactive != -1 ||
8411 Person::players[j]->animTarget == swordslashanim &&
8412 weaponactive != -1 ||
8413 Person::players[j]->animTarget == staffhitanim ||
8414 Person::players[j]->animTarget == staffspinhitanim)) {
8415 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
8416 Person::players[j]->victim == Person::players[id] &&
8417 (Person::players[j]->animTarget == sweepanim ||
8418 Person::players[j]->animTarget == spinkickanim ||
8419 Person::players[j]->animTarget == staffhitanim ||
8420 Person::players[j]->animTarget == staffspinhitanim ||
8421 Person::players[j]->animTarget == winduppunchanim ||
8422 Person::players[j]->animTarget == upunchanim ||
8423 Person::players[j]->animTarget == wolfslapanim ||
8424 Person::players[j]->animTarget == knifeslashstartanim ||
8425 Person::players[j]->animTarget == swordslashanim &&
8426 (distsq(&Person::players[j]->coords, &coords) < 2 ||
8427 weaponactive != -1))) {
8437 Person::players[target]->Reverse();
8444 if (collided > .8 && jumppower >= 5 ||
8445 distsq(&coords, &Person::players[0]->coords) > 400 &&
8447 creature == rabbittype) {
8450 //TODO: why are we controlling the human?
8451 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
8452 Person::players[0]->jumpkeydown = 0;
8454 if (Person::players[0]->animTarget == jumpdownanim &&
8455 distsq(&Person::players[0]->coords, &coords) < 40) {
8462 if (Tutorial::active) {
8468 XYZ facing = coords;
8469 XYZ flatfacing = Person::players[0]->coords;
8470 facing.y += jointPos(head).y * scale;
8471 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
8472 if (occluded >= 2) {
8473 if (-1 != Object::checkcollide(facing, flatfacing)) {
8477 if (lastseentime <= 0 &&
8478 (creature != wolftype ||
8479 weaponstuck == -1)) {
8480 aitype = searchtype;
8482 lastseen = Person::players[0]->coords;
8491 if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
8492 (aitype == attacktypecutoff ||
8493 aitype == searchtype)) {
8494 if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
8495 XYZ test = Person::players[0]->coords;
8497 if (-1 == Object::checkcollide(Person::players[0]->coords, test)) {
8503 if (aitype == passivetype && !(numwaypoints > 1) ||
8505 pause && damage > superpermanentdamage) {
8524 XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0);
8525 facing = flatfacing;
8527 if (aitype == attacktypecutoff) {
8528 targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
8529 targetheadpitch = pitchTo(coords, Person::players[0]->coords);
8530 } else if (howactive >= typesleeping) {
8531 targetheadyaw = targetyaw;
8532 targetheadpitch = 0;
8534 if (interestdelay <= 0) {
8535 interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
8536 headtarget = coords;
8537 headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
8538 headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
8539 headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
8540 headtarget += facing * 1.5;
8542 targetheadyaw = 180 - roughDirectionTo(coords, headtarget);
8543 targetheadpitch = pitchTo(coords, headtarget);