2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2017 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
21 #include "Objects/Person.hpp"
23 #include "Animation/Animation.hpp"
24 #include "Audio/Sounds.hpp"
25 #include "Audio/openal_wrapper.hpp"
27 #include "Level/Awards.hpp"
28 #include "Level/Dialog.hpp"
29 #include "Tutorial.hpp"
30 #include "Utils/Folders.hpp"
32 extern float multiplier;
33 extern Terrain terrain;
35 extern int environment;
37 extern FRUSTUM frustum;
39 extern float realmultiplier;
41 extern float slomodelay;
42 extern bool cellophane;
43 extern float texdetail;
44 extern float realtexdetail;
45 extern GLubyte bloodText[512 * 512 * 3];
46 extern GLubyte wolfbloodText[512 * 512 * 3];
47 extern int bloodtoggle;
48 extern bool autoslomo;
49 extern float camerashake;
51 extern float viewdistance;
52 extern float blackout;
53 extern int difficulty;
54 extern bool decalstoggle;
55 extern float fadestart;
57 extern bool winfreeze;
58 extern bool showpoints;
59 extern bool immediate;
60 extern float smoketex;
61 extern bool reversaltrain;
62 extern bool canattack;
64 extern float damagedealt;
66 extern float hostiletime;
68 extern bool gamestarted;
70 extern XYZ envsound[30];
71 extern float envsoundvol[30];
72 extern int numenvsounds;
73 extern float envsoundlife[30];
75 extern XYZ windvector;
77 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
78 std::vector<PersonType> PersonType::types;
80 void PersonType::Load()
85 types[wolftype].proportions[0] = 1.1;
86 types[wolftype].proportions[1] = 1.1;
87 types[wolftype].proportions[2] = 1.1;
88 types[wolftype].proportions[3] = 1.1;
90 types[wolftype].animRun = wolfrunanim;
91 types[wolftype].animRunning = wolfrunninganim;
92 types[wolftype].animCrouch = wolfcrouchanim;
93 types[wolftype].animStop = wolfstopanim;
94 types[wolftype].animLanding = wolflandanim;
95 types[wolftype].animLandingHard = wolflandhardanim;
97 types[wolftype].soundsAttack[0] = barksound;
98 types[wolftype].soundsAttack[1] = bark2sound;
99 types[wolftype].soundsAttack[2] = bark3sound;
100 types[wolftype].soundsAttack[3] = barkgrowlsound;
101 types[wolftype].soundsTalk[0] = growlsound;
102 types[wolftype].soundsTalk[1] = growl2sound;
104 types[wolftype].figureFileName = "Skeleton/BasicFigureWolf";
105 types[wolftype].lowFigureFileName = "Skeleton/BasicFigureWolfLow";
106 types[wolftype].clothesFileName = "Skeleton/RabbitBelt";
107 types[wolftype].modelFileNames[0] = "Models/Wolf.solid";
108 types[wolftype].modelFileNames[1] = "Models/Wolf2.solid";
109 types[wolftype].modelFileNames[2] = "Models/Wolf3.solid";
110 types[wolftype].modelFileNames[3] = "Models/Wolf4.solid";
111 types[wolftype].modelFileNames[4] = "Models/Wolf5.solid";
112 types[wolftype].modelFileNames[5] = "Models/Wolf6.solid";
113 types[wolftype].modelFileNames[6] = "Models/Wolf7.solid";
114 types[wolftype].lowModelFileName = "Models/WolfLow.solid";
115 types[wolftype].modelClothesFileName = "Models/Belt.solid";
118 types[rabbittype].proportions[0] = 1.2;
119 types[rabbittype].proportions[1] = 1.05;
120 types[rabbittype].proportions[2] = 1;
121 types[rabbittype].proportions[3] = 1.1;
122 types[rabbittype].proportions[3].y = 1.05;
124 types[rabbittype].animRun = runanim;
125 types[rabbittype].animRunning = rabbitrunninganim;
126 types[rabbittype].animCrouch = crouchanim;
127 types[rabbittype].animStop = stopanim;
128 types[rabbittype].animLanding = landanim;
129 types[rabbittype].animLandingHard = landhardanim;
131 types[rabbittype].soundsAttack[0] = rabbitattacksound;
132 types[rabbittype].soundsAttack[1] = rabbitattack2sound;
133 types[rabbittype].soundsAttack[2] = rabbitattack3sound;
134 types[rabbittype].soundsAttack[3] = rabbitattack4sound;
135 types[rabbittype].soundsTalk[0] = rabbitchitter;
136 types[rabbittype].soundsTalk[1] = rabbitchitter2;
138 types[rabbittype].figureFileName = "Skeleton/BasicFigure";
139 types[rabbittype].lowFigureFileName = "Skeleton/BasicFigureLow";
140 types[rabbittype].clothesFileName = "Skeleton/RabbitBelt";
141 types[rabbittype].modelFileNames[0] = "Models/Body.solid";
142 types[rabbittype].modelFileNames[1] = "Models/Body2.solid";
143 types[rabbittype].modelFileNames[2] = "Models/Body3.solid";
144 types[rabbittype].modelFileNames[3] = "Models/Body4.solid";
145 types[rabbittype].modelFileNames[4] = "Models/Body5.solid";
146 types[rabbittype].modelFileNames[5] = "Models/Body6.solid";
147 types[rabbittype].modelFileNames[6] = "Models/Body7.solid";
148 types[rabbittype].lowModelFileName = "Models/BodyLow.solid";
149 types[rabbittype].modelClothesFileName = "Models/Belt.solid";
155 , animCurrent(bounceidleanim)
156 , animTarget(bounceidleanim)
163 , howactive(typeactive)
165 , superruntoggle(false)
199 , rabbitkickenabled(false)
213 , superpermanentdamage(0)
256 , normalsupdatedelay(0)
260 , forwardkeydown(false)
261 , forwardstogglekeydown(false)
262 , rightkeydown(false)
266 , jumptogglekeydown(false)
267 , crouchkeydown(false)
268 , crouchtogglekeydown(false)
270 , drawtogglekeydown(false)
271 , throwkeydown(false)
272 , throwtogglekeydown(false)
273 , attackkeydown(false)
295 , whichdirection(false)
296 , whichdirectiondelay(0)
297 , avoidsomething(false)
307 , lefthandmorphness(0)
308 , righthandmorphness(0)
312 , targetlefthandmorphness(0)
313 , targetrighthandmorphness(0)
314 , targetheadmorphness(1)
315 , targetchestmorphness(0)
316 , targettailmorphness(0)
317 , lefthandmorphstart(0)
318 , lefthandmorphend(0)
319 , righthandmorphstart(0)
320 , righthandmorphend(0)
330 , highreversaldelay(0)
331 , lowreversaldelay(0)
380 , weaponstuckwhere(0)
393 , finalpathfindpoint(0)
394 , targetpathfindpoint(0)
395 , lastpathfindpoint(0)
396 , lastpathfindpoint2(0)
397 , lastpathfindpoint3(0)
398 , lastpathfindpoint4(0)
418 , neckspurtparticledelay(0)
423 , rabbitkickragdoll(false)
431 setProportions(1, 1, 1, 1);
434 /* Read a person in tfile. Throws an error if it’s not valid */
435 Person::Person(FILE* tfile, int mapvers, unsigned i)
439 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
441 funpackf(tfile, "Bi", &howactive);
443 howactive = typeactive;
446 funpackf(tfile, "Bf", &scale);
451 funpackf(tfile, "Bb", &immobile);
456 funpackf(tfile, "Bf", &yaw);
461 if (num_weapons < 0 || num_weapons > 5) {
462 throw InvalidPersonException();
464 if (num_weapons > 0 && num_weapons < 5) {
465 for (int j = 0; j < num_weapons; j++) {
466 weaponids[j] = weapons.size();
468 funpackf(tfile, "Bi", &type);
469 weapons.push_back(Weapon(type, id));
472 funpackf(tfile, "Bi", &numwaypoints);
473 for (int j = 0; j < numwaypoints; j++) {
474 funpackf(tfile, "Bf", &waypoints[j].x);
475 funpackf(tfile, "Bf", &waypoints[j].y);
476 funpackf(tfile, "Bf", &waypoints[j].z);
478 funpackf(tfile, "Bi", &waypointtype[j]);
480 waypointtype[j] = wpkeepwalking;
484 funpackf(tfile, "Bi", &waypoint);
485 if (waypoint > (numwaypoints - 1)) {
489 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
490 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
491 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
492 funpackf(tfile, "Bf Bf", &power, &speedmult);
495 funpackf(tfile, "Bf Bf Bf Bf", &proportions[0], &proportions[1], &proportions[2], &proportions[3]);
497 setProportions(1, 1, 1, 1);
500 funpackf(tfile, "Bi", &numclothes);
501 for (int k = 0; k < numclothes; k++) {
503 funpackf(tfile, "Bi", &templength);
504 for (int l = 0; l < templength; l++) {
505 funpackf(tfile, "Bb", &clothes[k][l]);
507 clothes[k][templength] = '\0';
508 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
514 if (creature == wolftype) {
516 damagetolerance = 300;
523 realoldcoords = coords;
526 void Person::skeletonLoad(bool clothes)
530 PersonType::types[creature].figureFileName,
531 PersonType::types[creature].lowFigureFileName,
532 PersonType::types[creature].clothesFileName,
533 PersonType::types[creature].modelFileNames[0],
534 PersonType::types[creature].modelFileNames[1],
535 PersonType::types[creature].modelFileNames[2],
536 PersonType::types[creature].modelFileNames[3],
537 PersonType::types[creature].modelFileNames[4],
538 PersonType::types[creature].modelFileNames[5],
539 PersonType::types[creature].modelFileNames[6],
540 PersonType::types[creature].lowModelFileName,
541 PersonType::types[creature].modelClothesFileName,
544 skeleton.drawmodel.textureptr.load(creatureskin[creature][whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
547 void Person::setProportions(float head, float body, float arms, float legs)
549 proportions[0] = head;
550 proportions[1] = body;
551 proportions[2] = arms;
552 proportions[3] = legs;
555 XYZ Person::getProportion(int part) const
557 XYZ prop = PersonType::types[creature].proportions[part] * proportions[part];
567 * GameTick/doPlayerCollisions
569 void Person::CheckKick()
571 if (!(hasvictim && (animTarget == rabbitkickanim && victim && victim != this->shared_from_this() && frameCurrent >= 2 && animCurrent == rabbitkickanim) && distsq(&coords, &victim->coords) < 1.2 && !victim->skeleton.free)) {
575 if (Animation::animations[victim->animTarget].height != lowheight) {
576 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
577 XYZ relative = velocity;
579 Normalise(&relative);
583 if (!Tutorial::active) {
584 emit_sound_at(heavyimpactsound, victim->coords);
587 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
588 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
591 victim->DoDamage(100 * damagemult / victim->protectionhigh);
598 animTarget = backflipanim;
600 velocity = facing * -10;
604 resume_stream(whooshsound);
607 award_bonus(id, cannon);
608 } else if (victim->isCrouch()) {
609 animTarget = rabbitkickreversedanim;
610 animCurrent = rabbitkickreversedanim;
611 victim->animCurrent = rabbitkickreversalanim;
612 victim->animTarget = rabbitkickreversalanim;
618 victim->oldcoords = victim->coords;
619 coords = victim->coords;
620 victim->targetyaw = targetyaw;
621 victim->victim = this->shared_from_this();
628 * GameTick::doPlayerCollisions - spread fire between players
629 * GameTick::ProcessDevKeys - press f to ignite
630 * Person::DoStuff - spread fire from lit campfires and bushes
632 void Person::CatchFire()
634 XYZ flatfacing, flatvelocity;
636 for (int i = 0; i < 10; i++) {
637 howmany = fabs(Random() % (skeleton.joints.size()));
639 flatvelocity = skeleton.joints[howmany].velocity;
640 flatfacing = skeleton.joints[howmany].position * scale + coords;
642 flatvelocity = velocity;
643 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
645 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
650 emit_sound_at(firestartsound, coords);
652 emit_stream_at(stream_firesound, coords);
660 * idle animation for this creature (depending on status)
662 int Person::getIdle()
664 if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype)) {
667 if (hasvictim && (victim != this->shared_from_this())) {
668 if ((!victim->dead && victim->aitype != passivetype &&
669 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
670 victim->id < Person::players.size())) {
671 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
672 if (creature == rabbittype) {
673 return fightidleanim;
675 if (creature == wolftype) {
679 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
680 if (weapons[weaponids[weaponactive]].getType() == knife) {
681 return knifefightidleanim;
683 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1) {
684 return swordfightidlebothanim;
686 if (weapons[weaponids[weaponactive]].getType() == sword) {
687 return swordfightidleanim;
689 if (weapons[weaponids[weaponactive]].getType() == staff) {
690 return swordfightidleanim;
693 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause) {
694 return fightsidestep;
698 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype) {
701 if (howactive == typesitting) {
704 if (howactive == typesittingwall) {
707 if (howactive == typesleeping) {
710 if (howactive == typedead1) {
713 if (howactive == typedead2) {
716 if (howactive == typedead3) {
719 if (howactive == typedead4) {
722 if (creature == rabbittype) {
723 return bounceidleanim;
725 if (creature == wolftype) {
732 * crouch animation for this creature
734 int Person::getCrouch()
736 return PersonType::types[creature].animCrouch;
740 * running animation for this creature (can be upright or all fours)
744 if (superruntoggle && (weaponactive == -1)) {
745 return PersonType::types[creature].animRunning;
747 return PersonType::types[creature].animRun;
753 int Person::getStop()
755 return PersonType::types[creature].animStop;
760 int Person::getLanding()
762 return PersonType::types[creature].animLanding;
767 int Person::getLandhard()
769 return PersonType::types[creature].animLandingHard;
775 * Person::DoAnimations
778 SolidHitBonus(int playerid)
780 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo) {
781 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
783 award_bonus(playerid, solidhit);
788 * spawns blood effects
790 void Person::DoBlood(float howmuch, int which)
792 // FIXME: should abstract out inputs
793 static int bleedxint, bleedyint;
795 if (bloodtoggle && !Tutorial::active) {
796 if (bleeding <= 0 && spurt) {
798 for (int i = 0; i < 3; i++) {
799 // emit blood particles
802 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
803 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
804 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
805 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
808 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
809 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
810 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
811 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
814 if (Random() % 2 == 0) { // 50% chance
815 for (int i = 0; i < 3; i++) {
816 if (Random() % 2 != 0) {
817 // emit teeth 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;
824 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
825 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
829 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
831 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
833 Sprite::setLastSpriteSpecial(3); // sets it to teeth
839 // FIXME: manipulating attributes
840 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
843 if (creature == rabbittype) {
844 while (bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
845 bleedxint = abs(Random() % 512);
846 bleedyint = abs(Random() % 512);
849 if (creature == wolftype) {
850 while (wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
851 bleedxint = abs(Random() % 512);
852 bleedyint = abs(Random() % 512);
857 bleedy /= realtexdetail;
858 bleedx /= realtexdetail;
859 direction = abs(Random() % 2) * 2 - 1;
868 * spawns big blood effects and ???
869 * modifies character's skin texture
871 void Person::DoBloodBig(float howmuch, int which)
873 static int bleedxint, bleedyint, i, j;
875 if (howmuch && id == 0) {
879 if (!Tutorial::active || id == 0) {
880 if (aitype != playercontrolled && howmuch > 0) {
884 if (creature == wolftype) {
885 int i = abs(Random() % 2);
887 whichsound = snarlsound;
890 whichsound = snarl2sound;
893 if (creature == rabbittype) {
894 int i = abs(Random() % 2);
896 whichsound = rabbitpainsound;
898 if (i == 1 && howmuch >= 2) {
899 whichsound = rabbitpain1sound;
903 if (whichsound != -1) {
904 emit_sound_at(whichsound, coords);
910 if (id == 0 && howmuch > 0) {
914 if (bloodtoggle && decalstoggle && !Tutorial::active) {
915 if (bleeding <= 0 && spurt) {
917 for (int i = 0; i < 3; i++) {
918 // emit blood particles
919 // FIXME: copypaste from above
922 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
923 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
924 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
925 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
928 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
929 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
930 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
931 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
936 // weird texture manipulation code follows.
937 // looks like this is painting blood onto the character's skin texture
938 // FIXME: surely there's a better way
940 int offsetx = 0, offsety = 0;
942 offsety = Random() % 40;
943 offsetx = abs(Random() % 60);
945 if (which == 190 || which == 185) {
946 offsety = Random() % 40;
947 offsetx = abs(Random() % 100) - 20;
950 offsety = Random() % 10;
951 offsetx = Random() % 10;
954 offsety = Random() % 20;
955 offsetx = Random() % 20;
957 if (which == 220 || which == 215) {
966 if (creature == rabbittype) {
967 for (i = 0; i < 512; i++) {
968 for (j = 0; j < 512; j++) {
969 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
986 if (creature == wolftype) {
987 for (i = 0; i < 512; i++) {
988 for (j = 0; j < 512; j++) {
989 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1018 if (endx > 512 - 1) {
1021 if (endy > 512 - 1) {
1024 if (endx < startx) {
1027 if (endy < starty) {
1031 startx /= realtexdetail;
1032 starty /= realtexdetail;
1033 endx /= realtexdetail;
1034 endy /= realtexdetail;
1036 int texdetailint = realtexdetail;
1038 if (creature == rabbittype) {
1039 for (i = startx; i < endx; i++) {
1040 for (j = starty; j < endy; j++) {
1041 if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
1042 color = Random() % 85 + 170;
1043 where = i * skeleton.skinsize * 3 + j * 3;
1044 if (skeleton.skinText[where + 0] > color / 2) {
1045 skeleton.skinText[where + 0] = color / 2;
1047 skeleton.skinText[where + 1] = 0;
1048 skeleton.skinText[where + 2] = 0;
1053 if (creature == wolftype) {
1054 for (i = startx; i < endx; i++) {
1055 for (j = starty; j < endy; j++) {
1056 if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
1057 color = Random() % 85 + 170;
1058 where = i * skeleton.skinsize * 3 + j * 3;
1059 if (skeleton.skinText[where + 0] > color / 2) {
1060 skeleton.skinText[where + 0] = color / 2;
1062 skeleton.skinText[where + 1] = 0;
1063 skeleton.skinText[where + 2] = 0;
1068 skeleton.drawmodel.textureptr.bind();
1073 if (creature == rabbittype) {
1074 while (bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
1075 bleedxint = abs(Random() % 512);
1076 bleedyint = abs(Random() % 512);
1079 if (creature == wolftype) {
1080 while (wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
1081 bleedxint = abs(Random() % 512);
1082 bleedyint = abs(Random() % 512);
1085 bleedy = bleedxint + offsetx;
1086 bleedx = bleedyint + offsety;
1087 bleedy /= realtexdetail;
1088 bleedx /= realtexdetail;
1095 if (bleedx > skeleton.skinsize - 1) {
1096 bleedx = skeleton.skinsize - 1;
1098 if (bleedy > skeleton.skinsize - 1) {
1099 bleedy = skeleton.skinsize - 1;
1101 direction = abs(Random() % 2) * 2 - 1;
1103 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1104 deathbleeding += bleeding;
1105 bloodloss += bleeding * 3;
1107 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1108 if (abs(Random() % 2) == 0) {
1109 aitype = gethelptype;
1112 aitype = attacktypecutoff;
1122 * similar to DoBloodBig
1124 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
1127 static XYZ bloodvel;
1128 static XYZ startpoint, endpoint, colpoint, movepoint;
1129 static float rotationpoint;
1130 static int whichtri;
1131 static XYZ p1, p2, p3, p0;
1134 float coordsx, coordsy;
1137 if (bloodtoggle && decalstoggle && !Tutorial::active) {
1139 if (!skeleton.free) {
1140 where = DoRotation(where, 0, -yaw, 0);
1144 startpoint.y += 100;
1149 // ray testing for a tri in the character model
1150 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
1151 if (whichtri != -1) {
1152 // low level geometry math
1154 p1 = skeleton.drawmodel.getTriangleVertex(whichtri, 0);
1155 p2 = skeleton.drawmodel.getTriangleVertex(whichtri, 1);
1156 p3 = skeleton.drawmodel.getTriangleVertex(whichtri, 2);
1158 bary.x = distsq(&p0, &p1);
1159 bary.y = distsq(&p0, &p2);
1160 bary.z = distsq(&p0, &p3);
1162 total = bary.x + bary.y + bary.z;
1167 bary.x = 1 - bary.x;
1168 bary.y = 1 - bary.y;
1169 bary.z = 1 - bary.z;
1171 total = bary.x + bary.y + bary.z;
1176 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1177 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1178 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1179 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1180 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1181 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1182 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;
1183 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;
1185 if (bleeding <= 0 && spurt) {
1187 for (int i = 0; i < 3; i++) {
1188 // emit blood particles
1189 // FIXME: more copypaste code
1191 if (skeleton.free) {
1192 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1193 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1194 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1195 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1198 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1199 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1200 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1201 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1206 // texture manipulation follows
1208 int offsetx = 0, offsety = 0;
1209 offsetx = (1 + coordsy) * 512 - 291;
1210 offsety = coordsx * 512 - 437;
1217 if (creature == rabbittype) {
1218 for (i = 0; i < 512; i++) {
1219 for (j = 0; j < 512; j++) {
1220 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1237 if (creature == wolftype) {
1238 for (i = 0; i < 512; i++) {
1239 for (j = 0; j < 512; j++) {
1240 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1268 if (endx > 512 - 1) {
1271 if (endy > 512 - 1) {
1274 if (endx < startx) {
1277 if (endy < starty) {
1281 startx /= realtexdetail;
1282 starty /= realtexdetail;
1283 endx /= realtexdetail;
1284 endy /= realtexdetail;
1286 int texdetailint = realtexdetail;
1288 if (creature == rabbittype) {
1289 for (i = startx; i < endx; i++) {
1290 for (j = starty; j < endy; j++) {
1291 if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
1292 color = Random() % 85 + 170;
1293 where = i * skeleton.skinsize * 3 + j * 3;
1294 if (skeleton.skinText[where + 0] > color / 2) {
1295 skeleton.skinText[where + 0] = color / 2;
1297 skeleton.skinText[where + 1] = 0;
1298 skeleton.skinText[where + 2] = 0;
1299 } else if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= 160 + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= 160 - 4) {
1300 color = Random() % 85 + 170;
1301 where = i * skeleton.skinsize * 3 + j * 3;
1302 if (skeleton.skinText[where + 0] > color / 2) {
1303 skeleton.skinText[where + 0] = color / 2;
1305 skeleton.skinText[where + 1] = 0;
1306 skeleton.skinText[where + 2] = 0;
1311 if (creature == wolftype) {
1312 for (i = startx; i < endx; i++) {
1313 for (j = starty; j < endy; j++) {
1314 if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
1315 color = Random() % 85 + 170;
1316 where = i * skeleton.skinsize * 3 + j * 3;
1317 if (skeleton.skinText[where + 0] > color / 2) {
1318 skeleton.skinText[where + 0] = color / 2;
1320 skeleton.skinText[where + 1] = 0;
1321 skeleton.skinText[where + 2] = 0;
1322 } else if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= 160 + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= 160 - 4) {
1323 color = Random() % 85 + 170;
1324 where = i * skeleton.skinsize * 3 + j * 3;
1325 if (skeleton.skinText[where + 0] > color / 2) {
1326 skeleton.skinText[where + 0] = color / 2;
1328 skeleton.skinText[where + 1] = 0;
1329 skeleton.skinText[where + 2] = 0;
1334 skeleton.drawmodel.textureptr.bind();
1337 bleedy = (1 + coordsy) * 512;
1338 bleedx = coordsx * 512;
1339 bleedy /= realtexdetail;
1340 bleedx /= realtexdetail;
1347 if (bleedx > skeleton.skinsize - 1) {
1348 bleedx = skeleton.skinsize - 1;
1350 if (bleedy > skeleton.skinsize - 1) {
1351 bleedy = skeleton.skinsize - 1;
1353 direction = abs(Random() % 2) * 2 - 1;
1355 if (whichtri == -1) {
1359 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1360 deathbleeding += bleeding;
1361 bloodloss += bleeding * 3;
1363 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1364 if (abs(Random() % 2) == 0) {
1365 aitype = gethelptype;
1368 aitype = attacktypecutoff;
1379 * guessing this performs a reversal
1381 void Person::Reverse()
1383 if (!((victim->aitype == playercontrolled || hostiletime > 1 || staggerdelay <= 0) && victim->animTarget != jumpupanim && victim->animTarget != jumpdownanim && (!Tutorial::active || cananger) && hostile)) {
1387 if (normaldotproduct(victim->facing, victim->coords - coords) > 0 && (victim->id != 0 || difficulty >= 2) && (creature != wolftype || victim->creature == wolftype)) {
1391 if (animTarget == sweepanim) {
1392 animTarget = sweepreversedanim;
1393 animCurrent = sweepreversedanim;
1394 victim->animCurrent = sweepreversalanim;
1395 victim->animTarget = sweepreversalanim;
1397 if (animTarget == spinkickanim) {
1398 animTarget = spinkickreversedanim;
1399 animCurrent = spinkickreversedanim;
1400 victim->animCurrent = spinkickreversalanim;
1401 victim->animTarget = spinkickreversalanim;
1403 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1404 if (animTarget == rabbittacklinganim) {
1407 victim->frameCurrent = 6;
1408 victim->frameTarget = 7;
1410 animTarget = upunchreversedanim;
1411 animCurrent = upunchreversedanim;
1412 victim->animCurrent = upunchreversalanim;
1413 victim->animTarget = upunchreversalanim;
1415 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1416 if (victim->weaponactive != -1) {
1417 victim->throwtogglekeydown = 1;
1418 XYZ tempVelocity = victim->velocity * .2;
1419 if (tempVelocity.x == 0) {
1420 tempVelocity.x = .1;
1422 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1423 victim->num_weapons--;
1424 if (victim->num_weapons) {
1425 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1426 if (victim->weaponstuck == victim->num_weapons) {
1427 victim->weaponstuck = 0;
1431 victim->weaponactive = -1;
1432 for (unsigned j = 0; j < Person::players.size(); j++) {
1433 Person::players[j]->wentforweapon = 0;
1437 animTarget = staffhitreversedanim;
1438 animCurrent = staffhitreversedanim;
1439 victim->animCurrent = staffhitreversalanim;
1440 victim->animTarget = staffhitreversalanim;
1442 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1443 if (victim->weaponactive != -1) {
1444 victim->throwtogglekeydown = 1;
1445 XYZ tempVelocity = victim->velocity * .2;
1446 if (tempVelocity.x == 0) {
1447 tempVelocity.x = .1;
1449 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1450 victim->num_weapons--;
1451 if (victim->num_weapons) {
1452 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1453 if (victim->weaponstuck == victim->num_weapons) {
1454 victim->weaponstuck = 0;
1458 victim->weaponactive = -1;
1459 for (unsigned j = 0; j < Person::players.size(); j++) {
1460 Person::players[j]->wentforweapon = 0;
1463 animTarget = staffspinhitreversedanim;
1464 animCurrent = staffspinhitreversedanim;
1465 victim->animCurrent = staffspinhitreversalanim;
1466 victim->animTarget = staffspinhitreversalanim;
1468 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1469 if (victim->weaponactive != -1) {
1470 victim->throwtogglekeydown = 1;
1471 XYZ tempVelocity = victim->velocity * .2;
1472 if (tempVelocity.x == 0) {
1473 tempVelocity.x = .1;
1475 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1476 victim->num_weapons--;
1477 if (victim->num_weapons) {
1478 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1479 if (victim->weaponstuck == victim->num_weapons) {
1480 victim->weaponstuck = 0;
1484 victim->weaponactive = -1;
1485 for (unsigned j = 0; j < Person::players.size(); j++) {
1486 Person::players[j]->wentforweapon = 0;
1489 animTarget = swordslashreversedanim;
1490 animCurrent = swordslashreversedanim;
1491 victim->animCurrent = swordslashreversalanim;
1492 victim->animTarget = swordslashreversalanim;
1494 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1495 if (victim->weaponactive != -1) {
1496 victim->throwtogglekeydown = 1;
1497 XYZ tempVelocity = victim->velocity * .2;
1498 if (tempVelocity.x == 0) {
1499 tempVelocity.x = .1;
1501 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1502 victim->num_weapons--;
1503 if (victim->num_weapons) {
1504 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1505 if (victim->weaponstuck == victim->num_weapons) {
1506 victim->weaponstuck = 0;
1510 victim->weaponactive = -1;
1511 for (unsigned j = 0; j < Person::players.size(); j++) {
1512 Person::players[j]->wentforweapon = 0;
1515 animTarget = knifeslashreversedanim;
1516 animCurrent = knifeslashreversedanim;
1517 victim->animCurrent = knifeslashreversalanim;
1518 victim->animTarget = knifeslashreversalanim;
1520 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1521 victim->targettilt2 = targettilt2;
1522 victim->frameCurrent = frameCurrent;
1523 victim->frameTarget = frameTarget;
1524 victim->target = target;
1525 victim->velocity = 0;
1526 victim->oldcoords = victim->coords;
1527 victim->coords = coords;
1528 victim->targetyaw = targetyaw;
1529 victim->yaw = targetyaw;
1530 victim->victim = this->shared_from_this();
1532 if (animTarget == winduppunchanim) {
1533 animTarget = winduppunchblockedanim;
1534 victim->animTarget = blockhighleftanim;
1535 victim->frameTarget = 1;
1536 victim->target = .5;
1537 victim->victim = this->shared_from_this();
1538 victim->targetyaw = targetyaw + 180;
1540 if (animTarget == wolfslapanim) {
1541 animTarget = winduppunchblockedanim;
1542 victim->animTarget = blockhighleftanim;
1543 victim->frameTarget = 1;
1544 victim->target = .5;
1545 victim->victim = this->shared_from_this();
1546 victim->targetyaw = targetyaw + 180;
1548 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1549 animTarget = swordslashparriedanim;
1550 parriedrecently = .4;
1551 victim->parriedrecently = 0;
1552 victim->animTarget = swordslashparryanim;
1553 victim->frameTarget = 1;
1554 victim->target = .5;
1555 victim->victim = this->shared_from_this();
1556 victim->targetyaw = targetyaw + 180;
1558 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1559 if (victim->weaponactive != -1) {
1560 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1561 if (weapons[victim->weaponids[0]].getType() == staff) {
1562 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1564 if (weapons[weaponids[0]].getType() == staff) {
1565 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1567 emit_sound_at(swordstaffsound, victim->coords);
1569 emit_sound_at(metalhitsound, victim->coords);
1573 victim->Puff(righthand);
1575 victim->frameTarget = 0;
1576 victim->animTarget = staggerbackhighanim;
1577 victim->targetyaw = targetyaw + 180;
1579 aim = DoRotation(facing, 0, 90, 0) * 21;
1581 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1582 victim->num_weapons--;
1583 if (victim->num_weapons) {
1584 victim->weaponids[0] = victim->weaponids[num_weapons];
1585 if (victim->weaponstuck == victim->num_weapons) {
1586 victim->weaponstuck = 0;
1589 victim->weaponactive = -1;
1590 for (unsigned i = 0; i < Person::players.size(); i++) {
1591 Person::players[i]->wentforweapon = 0;
1595 if (abs(Random() % 20) == 0) {
1596 if (weaponactive != -1) {
1597 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1598 if (weapons[victim->weaponids[0]].getType() == staff) {
1599 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1601 if (weapons[weaponids[0]].getType() == staff) {
1602 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1605 emit_sound_at(swordstaffsound, coords);
1607 emit_sound_at(metalhitsound, coords);
1615 animTarget = staggerbackhighanim;
1616 targetyaw = targetyaw + 180;
1618 aim = DoRotation(facing, 0, 90, 0) * 21;
1620 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1623 weaponids[0] = weaponids[num_weapons];
1624 if (weaponstuck == num_weapons) {
1629 for (unsigned i = 0; i < Person::players.size(); i++) {
1630 Person::players[i]->wentforweapon = 0;
1635 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1636 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1637 victim->animTarget = dodgebackanim;
1638 victim->frameTarget = 0;
1642 rotatetarget = coords - victim->coords;
1643 Normalise(&rotatetarget);
1644 victim->targetyaw = -asin(0 - rotatetarget.x);
1645 victim->targetyaw *= 360 / 6.28;
1646 if (rotatetarget.z < 0) {
1647 victim->targetyaw = 180 - victim->targetyaw;
1650 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1652 victim->lastattack3 = victim->lastattack2;
1653 victim->lastattack2 = victim->lastattack;
1654 victim->lastattack = victim->animTarget;
1656 victim->animTarget = sweepanim;
1657 victim->frameTarget = 0;
1661 rotatetarget = coords - victim->coords;
1662 Normalise(&rotatetarget);
1663 victim->targetyaw = -asin(0 - rotatetarget.x);
1664 victim->targetyaw *= 360 / 6.28;
1665 if (rotatetarget.z < 0) {
1666 victim->targetyaw = 180 - victim->targetyaw;
1669 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1671 victim->lastattack3 = victim->lastattack2;
1672 victim->lastattack2 = victim->lastattack;
1673 victim->lastattack = victim->animTarget;
1679 victim->velocity = 0;
1681 if (aitype != playercontrolled) {
1683 if (escapednum < 2) {
1684 int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
1685 if ((Random() % chances) == 0) {
1691 if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal) {
1699 void Person::DoDamage(float howmuch)
1703 damagetaken += howmuch / power;
1705 damagedealt += howmuch / power;
1709 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo)) {
1714 if (!Tutorial::active) {
1715 damage += howmuch / power;
1716 permanentdamage += howmuch / 2 / power;
1717 superpermanentdamage += howmuch / 4 / power;
1720 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2) {
1723 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt) {
1728 camerashake += howmuch / 100;
1729 if ((howmuch > 50 && damage > damagetolerance / 2)) {
1730 blackout = damage / damagetolerance;
1738 if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile)) {
1739 aitype = attacktypecutoff;
1741 if (!Tutorial::active && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1742 if (abs(Random() % 2) == 0) {
1743 aitype = gethelptype;
1746 aitype = attacktypecutoff;
1751 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1754 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1755 if (skeleton.free) {
1756 flatvelocity2 = skeleton.joints[i].velocity;
1757 flatfacing2 = skeleton.joints[i].position * scale + coords;
1759 flatvelocity2 = velocity;
1760 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1762 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1763 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1764 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1765 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1766 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1767 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1770 emit_sound_at(splattersound, coords);
1775 if (!dead && creature == wolftype) {
1776 award_bonus(0, Wolfbonus);
1783 if (!Tutorial::active || id == 0) {
1784 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1785 int whichsound = -1;
1787 if (creature == wolftype) {
1788 int i = abs(Random() % 2);
1790 whichsound = snarlsound;
1793 whichsound = snarl2sound;
1796 if (creature == rabbittype) {
1797 int i = abs(Random() % 2);
1799 whichsound = rabbitpainsound;
1801 if (i == 1 && damage > damagetolerance) {
1802 whichsound = rabbitpain1sound;
1806 if (whichsound != -1) {
1807 emit_sound_at(whichsound, coords);
1808 addEnvSound(coords);
1816 * calculate/animate head facing direction?
1818 void Person::DoHead()
1820 static XYZ rotatearound;
1822 static float lookspeed = 500;
1824 if (!freeze && !winfreeze) {
1827 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1828 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1830 while (targetheadyaw > 180) {
1831 targetheadyaw -= 360;
1833 while (targetheadyaw < -180) {
1834 targetheadyaw += 360;
1837 if (targetheadyaw > 160) {
1838 targetheadpitch = targetheadpitch * -1;
1840 if (targetheadyaw < -160) {
1841 targetheadpitch = targetheadpitch * -1;
1843 if (targetheadyaw > 160) {
1844 targetheadyaw = targetheadyaw - 180;
1846 if (targetheadyaw < -160) {
1847 targetheadyaw = targetheadyaw + 180;
1850 if (targetheadpitch > 120) {
1851 targetheadpitch = 120;
1853 if (targetheadpitch < -120) {
1854 targetheadpitch = -120;
1856 if (targetheadyaw > 120) {
1857 targetheadyaw = 120;
1859 if (targetheadyaw < -120) {
1860 targetheadyaw = -120;
1864 targetheadpitch = 0;
1867 if (targetheadyaw > 80) {
1870 if (targetheadyaw < -80) {
1871 targetheadyaw = -80;
1873 if (targetheadpitch > 50) {
1874 targetheadpitch = 50;
1876 if (targetheadpitch < -50) {
1877 targetheadpitch = -50;
1881 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed) {
1882 headyaw = targetheadyaw;
1883 } else if (headyaw > targetheadyaw) {
1884 headyaw -= multiplier * lookspeed;
1885 } else if (headyaw < targetheadyaw) {
1886 headyaw += multiplier * lookspeed;
1889 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2) {
1890 headpitch = targetheadpitch;
1891 } else if (headpitch > targetheadpitch) {
1892 headpitch -= multiplier * lookspeed / 2;
1893 } else if (headpitch < targetheadpitch) {
1894 headpitch += multiplier * lookspeed / 2;
1897 rotatearound = jointPos(neck);
1898 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1902 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1903 facing = DoRotation(facing, headpitch * .4, 0, 0);
1904 facing = DoRotation(facing, 0, headyaw * .4, 0);
1907 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1908 facing = DoRotation(facing, headpitch * .8, 0, 0);
1909 facing = DoRotation(facing, 0, headyaw * .8, 0);
1912 if (animTarget == walkanim) {
1913 facing = DoRotation(facing, headpitch * .6, 0, 0);
1914 facing = DoRotation(facing, 0, headyaw * .6, 0);
1917 skeleton.specialforward[0] = facing;
1918 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1919 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
1920 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1921 skeleton.FindRotationMuscle(i, animTarget);
1928 * ragdolls character?
1930 void Person::RagDoll(bool checkcollision)
1935 if (!skeleton.free) {
1939 if (id == 0 && isFlip()) {
1947 facing = DoRotation(facing, 0, yaw, 0);
1949 skeleton.freetime = 0;
1951 skeleton.longdead = 0;
1954 skeleton.broken = 0;
1955 skeleton.spinny = 1;
1957 skeleton.freefall = 1;
1959 if (!isnormal(velocity.x)) {
1962 if (!isnormal(velocity.y)) {
1965 if (!isnormal(velocity.z)) {
1968 if (!isnormal(yaw)) {
1971 if (!isnormal(coords.x)) {
1974 if (!isnormal(tilt)) {
1977 if (!isnormal(tilt2)) {
1981 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1982 skeleton.joints[i].delay = 0;
1983 skeleton.joints[i].locked = 0;
1984 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1985 if (!isnormal(skeleton.joints[i].position.x)) {
1986 skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1988 if (!isnormal(skeleton.joints[i].position.x)) {
1989 skeleton.joints[i].position = coords;
1991 skeleton.joints[i].position.y += .1;
1992 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1993 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1996 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1997 skeleton.joints[i].velocity = 0;
1998 skeleton.joints[i].velchange = 0;
2000 skeleton.DoConstraints(&coords, &scale);
2001 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
2002 skeleton.DoConstraints(&coords, &scale);
2003 skeleton.DoConstraints(&coords, &scale);
2004 skeleton.DoConstraints(&coords, &scale);
2005 skeleton.DoConstraints(&coords, &scale);
2008 speed = targetFrame().speed * 2;
2009 if (currentFrame().speed > targetFrame().speed) {
2010 speed = currentFrame().speed * 2;
2013 speed = transspeed * 2;
2018 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
2019 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height) {
2020 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);
2022 skeleton.joints[i].velocity = velocity / scale + facing * 5;
2024 change.x = (float)(Random() % 100) / 100;
2025 change.y = (float)(Random() % 100) / 100;
2026 change.z = (float)(Random() % 100) / 100;
2027 skeleton.joints[i].velocity += change;
2028 skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change;
2030 change.x = (float)(Random() % 100) / 100;
2031 change.y = (float)(Random() % 100) / 100;
2032 change.z = (float)(Random() % 100) / 100;
2033 skeleton.joints[i].velchange += change;
2034 skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change;
2037 if (checkcollision) {
2040 if (!skeleton.joints.empty()) {
2043 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
2044 average += skeleton.joints[j].position;
2046 average /= skeleton.joints.size();
2047 coords += average * scale;
2048 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
2049 skeleton.joints[j].position -= average;
2053 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
2054 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
2055 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
2056 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
2059 if (SphereCheck(&lowpoint, 3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
2060 coords.x = lowpoint.x;
2061 coords.z = lowpoint.z;
2070 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
2071 velocity += skeleton.joints[i].velocity * scale;
2073 velocity /= skeleton.joints.size();
2076 if (Random() % 2 == 0) {
2077 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
2078 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
2079 weapons[weaponids[0]].velocity.x += .01;
2082 weaponids[0] = weaponids[num_weapons];
2083 if (weaponstuck == num_weapons) {
2088 for (unsigned i = 0; i < Person::players.size(); i++) {
2089 Person::players[i]->wentforweapon = 0;
2094 animTarget = bounceidleanim;
2095 animCurrent = bounceidleanim;
2103 void Person::FootLand(bodypart whichfoot, float opacity)
2105 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
2106 cerr << "FootLand called on wrong bodypart" << endl;
2109 static XYZ terrainlight;
2110 static XYZ footvel, footpoint;
2111 if (opacity >= 1 || skiddelay <= 0) {
2114 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2115 if (distsq(&footpoint, &viewer)) {
2116 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
2118 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
2119 footvel = velocity / 5;
2120 if (footvel.y < .8) {
2123 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2124 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
2125 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
2126 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
2127 if (environment == snowyenvironment) {
2128 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
2130 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
2132 } else if (environment == grassyenvironment) {
2133 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
2134 } else if (environment == desertenvironment) {
2135 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
2137 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
2141 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
2142 footvel = velocity / 5;
2143 if (footvel.y < .8) {
2146 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2147 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
2148 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
2155 * make a puff effect at a body part (dust effect?)
2157 void Person::Puff(int whichlabel)
2159 static XYZ footvel, footpoint;
2162 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
2163 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
2167 * I think I added this in an attempt to clean up code
2169 void Person::setTargetAnimation(int animation)
2171 animTarget = animation;
2180 void Person::DoAnimations()
2182 if (!skeleton.free) {
2183 static float oldtarget;
2185 if (isIdle() && animCurrent != getIdle()) {
2186 normalsupdatedelay = 0;
2189 if (animTarget == tempanim || animCurrent == tempanim) {
2190 Animation::animations[tempanim] = tempanimation;
2192 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
2199 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
2200 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
2202 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z)) {
2205 if (!crouchkeydown && velocity.y >= -15) {
2209 if ((animCurrent == jumpupanim || animTarget == jumpdownanim) /*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
2214 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
2216 if (normaldotproduct(targfacing, velocity) >= -.3) {
2217 animTarget = flipanim;
2219 animTarget = backflipanim;
2221 crouchtogglekeydown = 1;
2230 if (Animation::animations[animTarget].attack != reversed) {
2233 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
2234 crouchtogglekeydown = 0;
2235 if (aitype == playercontrolled) {
2239 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain)) {
2243 crouchtogglekeydown = 1;
2247 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
2249 normalsupdatedelay = 0;
2254 if (animTarget == rollanim && frameTarget == 3 && onfire) {
2256 emit_sound_at(fireendsound, coords);
2257 pause_sound(stream_firesound);
2261 if (animTarget == rabbittacklinganim && frameTarget == 1) {
2262 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0) {
2265 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
2266 if (normaldotproduct(victim->facing, facing) > 0) {
2267 victim->animTarget = rabbittackledbackanim;
2269 victim->animTarget = rabbittackledfrontanim;
2271 victim->frameTarget = 2;
2274 victim->targetyaw = yaw;
2275 if (victim->aitype == gethelptype) {
2276 victim->DoDamage(victim->damagetolerance - victim->damage);
2278 //victim->DoDamage(30);
2279 if (creature == wolftype) {
2281 emit_sound_at(clawslicesound, victim->coords);
2283 victim->DoBloodBig(1 / victim->armorhead, 210);
2285 award_bonus(id, TackleBonus,
2286 victim->aitype == gethelptype ? 50 : 0);
2290 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2291 if (weapons[weaponids[0]].getType() == knife) {
2292 if (weaponactive == -1) {
2294 } else if (weaponactive == 0) {
2298 if (weaponactive == -1) {
2299 emit_sound_at(knifesheathesound, coords);
2301 if (weaponactive != -1) {
2302 emit_sound_at(knifedrawsound, coords, 128);
2305 drawtogglekeydown = 1;
2308 if (!Tutorial::active || id == 0) {
2309 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2310 int whichsound = -1;
2312 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2313 if (targetFrame().label == 1) {
2314 whichsound = footstepsound;
2316 whichsound = footstepsound2;
2318 if (targetFrame().label == 1) {
2319 FootLand(leftfoot, 1);
2321 if (targetFrame().label == 2) {
2322 FootLand(rightfoot, 1);
2324 if (targetFrame().label == 3 && isRun()) {
2325 FootLand(rightfoot, 1);
2326 FootLand(leftfoot, 1);
2329 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2330 if (targetFrame().label == 1) {
2331 whichsound = footstepsound3;
2333 whichsound = footstepsound4;
2338 if (targetFrame().label == 1) {
2339 whichsound = footstepsound3;
2341 whichsound = footstepsound4;
2344 if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2345 if (Animation::animations[animTarget].attack != neutral) {
2346 unsigned r = abs(Random() % 3);
2348 whichsound = lowwhooshsound;
2351 whichsound = midwhooshsound;
2354 whichsound = highwhooshsound;
2357 if (Animation::animations[animTarget].attack == neutral) {
2358 whichsound = movewhooshsound;
2360 } else if (targetFrame().label == 4) {
2361 whichsound = knifeswishsound;
2363 if (targetFrame().label == 8 && !Tutorial::active) {
2364 whichsound = landsound2;
2367 if (whichsound != -1) {
2368 emit_sound_at(whichsound, coords, 256.);
2371 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2372 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2373 addEnvSound(coords, 15);
2375 addEnvSound(coords, 6);
2380 if (targetFrame().label == 3) {
2382 emit_sound_at(whichsound, coords, 128.);
2389 if (!Tutorial::active || id == 0) {
2390 if (speechdelay <= 0) {
2391 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
2392 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2393 int whichsound = -1;
2394 if (targetFrame().label == 4 && aitype != playercontrolled) {
2395 if (Animation::animations[animTarget].attack != neutral) {
2396 unsigned r = abs(Random() % 4);
2397 whichsound = PersonType::types[creature].soundsAttack[r];
2402 if (whichsound != -1) {
2403 emit_sound_at(whichsound, coords);
2410 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2411 FootLand(leftfoot, 1);
2412 FootLand(rightfoot, 1);
2416 currentoffset = targetoffset;
2417 frameTarget = frameCurrent;
2418 animCurrent = animTarget;
2421 if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2422 for (unsigned i = 0; i < weapons.size(); i++) {
2423 if (weapons[i].owner == -1) {
2424 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2425 if (distsq(&coords, &weapons[i].position) >= 1) {
2426 if (weapons[i].getType() != staff) {
2427 emit_sound_at(knifedrawsound, coords, 128.);
2437 if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2438 for (unsigned i = 0; i < weapons.size(); i++) {
2439 bool willwork = true;
2440 if (weapons[i].owner != -1) {
2441 if (Person::players[weapons[i].owner]->weaponstuck != -1) {
2442 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i)) {
2443 if (Person::players[weapons[i].owner]->num_weapons > 1) {
2449 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free)) {
2450 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2451 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2452 bool fleshstuck = false;
2453 if (weapons[i].owner != -1) {
2454 if (victim->weaponstuck != -1) {
2455 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2461 emit_sound_at(fleshstabremovesound, coords, 128.);
2463 if (weapons[i].getType() != staff) {
2464 emit_sound_at(knifedrawsound, coords, 128.);
2467 if (weapons[i].owner != -1) {
2468 victim = Person::players[weapons[i].owner];
2469 if (victim->num_weapons == 1) {
2470 victim->num_weapons = 0;
2472 victim->num_weapons = 1;
2475 //victim->weaponactive=-1;
2476 victim->skeleton.longdead = 0;
2477 victim->skeleton.free = 1;
2478 victim->skeleton.broken = 0;
2480 for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) {
2481 victim->skeleton.joints[j].velchange = 0;
2482 victim->skeleton.joints[j].locked = 0;
2488 Normalise(&relative);
2489 XYZ footvel, footpoint;
2491 footpoint = weapons[i].position;
2492 if (victim->weaponstuck != -1) {
2493 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2495 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2497 weapons[i].bloody = 2;
2498 weapons[i].blooddrip = 5;
2499 victim->weaponstuck = -1;
2502 if (victim->num_weapons > 0) {
2503 if (victim->weaponstuck != 0 && victim->weaponstuck != -1) {
2504 victim->weaponstuck = 0;
2506 if (victim->weaponids[0] == int(i)) {
2507 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2511 victim->jointVel(abdomen) += relative * 6;
2512 victim->jointVel(neck) += relative * 6;
2513 victim->jointVel(rightshoulder) += relative * 6;
2514 victim->jointVel(leftshoulder) += relative * 6;
2523 if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2524 if (weaponactive == -1) {
2526 } else if (weaponactive == 0) {
2528 if (num_weapons == 2) {
2530 buffer = weaponids[0];
2531 weaponids[0] = weaponids[1];
2532 weaponids[1] = buffer;
2535 if (weaponactive == -1) {
2536 emit_sound_at(knifesheathesound, coords, 128.);
2538 if (weaponactive != -1) {
2539 emit_sound_at(knifedrawsound, coords, 128.);
2543 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2544 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2545 Normalise(&rotatetarget);
2546 targetyaw = -asin(0 - rotatetarget.x);
2547 targetyaw *= 360 / 6.28;
2548 if (rotatetarget.z < 0) {
2549 targetyaw = 180 - targetyaw;
2552 if (animTarget == walljumprightkickanim) {
2555 if (animTarget == walljumpleftkickanim) {
2562 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0)) {
2566 if (distsq(&victim->coords, &/*Person::players[i]->*/ coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1) {
2574 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2575 animTarget = rabbittackleanim;
2577 emit_sound_at(jumpsound, coords);
2585 targetloc = velocity;
2586 Normalise(&targetloc);
2587 targetloc += coords;
2588 for (unsigned i = 0; i < Person::players.size(); i++) {
2590 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2591 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2596 if (closestid != -1) {
2597 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2599 victim = Person::players[closestid];
2600 coords = victim->coords;
2601 animCurrent = rabbittacklinganim;
2602 animTarget = rabbittacklinganim;
2606 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2607 rotatetarget = coords - victim->coords;
2608 Normalise(&rotatetarget);
2609 targetyaw = -asin(0 - rotatetarget.x);
2610 targetyaw *= 360 / 6.28;
2611 if (rotatetarget.z < 0) {
2612 targetyaw = 180 - targetyaw;
2615 if (animTarget != rabbitrunninganim) {
2616 emit_sound_at(jumpsound, coords, 128.);
2623 float damagemult = 1 * power;
2624 if (creature == wolftype) {
2625 damagemult = 2.5 * power;
2628 damagemult /= victim->damagetolerance / 200;
2630 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)) {
2631 if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2632 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2637 if (Random() % 2 || creature == wolftype) {
2640 if (creature == wolftype) {
2644 if (!Tutorial::active) {
2645 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2647 if (creature == wolftype) {
2648 emit_sound_at(clawslicesound, victim->coords, 128.);
2650 victim->DoBloodBig(2 / victim->armorhead, 175);
2654 relative = victim->coords - coords;
2656 Normalise(&relative);
2657 relative = DoRotation(relative, 0, -90, 0);
2658 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2659 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2661 victim->jointVel(head) += relative * damagemult * 200;
2663 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2669 if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2670 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2675 if (Random() % 2 || creature == wolftype) {
2677 if (creature == wolftype) {
2681 emit_sound_at(whooshhitsound, victim->coords);
2682 if (creature == wolftype) {
2683 emit_sound_at(clawslicesound, victim->coords, 128.);
2685 victim->DoBloodBig(2, 175);
2689 relative = victim->coords - coords;
2691 Normalise(&relative);
2693 Normalise(&relative);
2694 relative = DoRotation(relative, 0, 90, 0);
2695 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2696 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2698 victim->jointVel(head) += relative * damagemult * 100;
2700 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2704 if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2705 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2712 if (!Tutorial::active) {
2713 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2715 if (creature == wolftype) {
2716 emit_sound_at(clawslicesound, victim->coords, 128.);
2718 victim->DoBloodBig(2 / victim->armorhead, 175);
2724 Normalise(&relative);
2725 relative = DoRotation(relative, 0, -90, 0);
2726 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2727 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2729 victim->jointVel(head) += relative * damagemult * 200;
2731 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2733 if (victim->damage > victim->damagetolerance) {
2734 award_bonus(id, style);
2741 if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2742 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2749 if (!Tutorial::active) {
2750 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2752 if (creature == wolftype) {
2753 emit_sound_at(clawslicesound, victim->coords, 128.);
2755 victim->DoBloodBig(2 / victim->armorhead, 175);
2761 Normalise(&relative);
2762 relative = DoRotation(relative, 0, 90, 0);
2763 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2764 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2766 victim->jointVel(head) += relative * damagemult * 200;
2768 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2770 if (victim->damage > victim->damagetolerance) {
2771 award_bonus(id, style);
2778 if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2779 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2788 emit_sound_at(whooshhitsound, victim->coords);
2791 relative = victim->coords - coords;
2793 Normalise(&relative);
2794 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2795 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2797 victim->jointVel(head) += relative * damagemult * 100;
2799 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2803 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
2804 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2809 emit_sound_at(whooshhitsound, victim->coords, 128.);
2811 victim->skeleton.longdead = 0;
2812 victim->skeleton.free = 1;
2813 victim->skeleton.broken = 0;
2814 victim->skeleton.spinny = 1;
2816 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2817 victim->skeleton.joints[i].velchange = 0;
2818 victim->skeleton.joints[i].delay = 0;
2819 victim->skeleton.joints[i].locked = 0;
2820 //victim->skeleton.joints[i].velocity=0;
2826 Normalise(&relative);
2827 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2828 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2829 victim->skeleton.joints[i].position.y += relative.y * .3;
2830 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2831 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2833 victim->Puff(abdomen);
2834 victim->jointVel(abdomen).y = relative.y * 400;
2838 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2839 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2844 if (!Tutorial::active) {
2845 emit_sound_at(heavyimpactsound, coords, 128.);
2848 relative = victim->coords - coords;
2850 Normalise(&relative);
2851 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2852 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2854 victim->Puff(abdomen);
2855 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2859 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2860 victim->jointVel(abdomen) += relative * damagemult * 300;
2864 if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
2865 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2870 if (!Tutorial::active) {
2871 emit_sound_at(thudsound, coords);
2874 victim->skeleton.longdead = 0;
2875 victim->skeleton.free = 1;
2876 victim->skeleton.broken = 0;
2877 victim->skeleton.spinny = 1;
2879 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2880 victim->skeleton.joints[i].velchange = 0;
2881 //victim->skeleton.joints[i].delay=0;
2882 victim->skeleton.joints[i].locked = 0;
2885 relative = victim->coords - coords;
2886 Normalise(&relative);
2888 Normalise(&relative);
2889 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2890 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2892 if (!victim->dead) {
2896 victim->Puff(abdomen);
2897 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2898 victim->jointVel(abdomen) += relative * damagemult * 200;
2900 if (!victim->dead) {
2906 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2909 if (!victim->skeleton.free) {
2915 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2916 emit_sound_at(knifesheathesound, coords, 128.);
2919 if (victim && hasvictim) {
2920 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2922 XYZ where, startpoint, endpoint, movepoint, colpoint;
2923 float rotationpoint;
2925 if (weapons[weaponids[weaponactive]].getType() == knife) {
2926 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2927 where -= victim->coords;
2928 if (!victim->skeleton.free) {
2929 where = DoRotation(where, 0, -victim->yaw, 0);
2933 startpoint.y += 100;
2937 if (weapons[weaponids[weaponactive]].getType() == sword) {
2938 where = weapons[weaponids[weaponactive]].position;
2939 where -= victim->coords;
2940 if (!victim->skeleton.free) {
2941 where = DoRotation(where, 0, -victim->yaw, 0);
2944 where = weapons[weaponids[weaponactive]].tippoint;
2945 where -= victim->coords;
2946 if (!victim->skeleton.free) {
2947 where = DoRotation(where, 0, -victim->yaw, 0);
2951 if (weapons[weaponids[weaponactive]].getType() == staff) {
2952 where = weapons[weaponids[weaponactive]].position;
2953 where -= victim->coords;
2954 if (!victim->skeleton.free) {
2955 where = DoRotation(where, 0, -victim->yaw, 0);
2958 where = weapons[weaponids[weaponactive]].tippoint;
2959 where -= victim->coords;
2960 if (!victim->skeleton.free) {
2961 where = DoRotation(where, 0, -victim->yaw, 0);
2967 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2969 if (whichtri != -1) {
2970 if (victim->dead != 2) {
2971 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2972 if (!victim->dead) {
2973 award_bonus(id, FinishedBonus);
2977 weapons[weaponids[weaponactive]].bloody = 2;
2980 victim->skeleton.longdead = 0;
2981 victim->skeleton.free = 1;
2982 victim->skeleton.broken = 0;
2984 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2985 victim->skeleton.joints[i].velchange = 0;
2986 victim->skeleton.joints[i].locked = 0;
2987 //victim->skeleton.joints[i].velocity=0;
2989 emit_sound_at(fleshstabsound, coords, 128);
2991 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2992 weapons[weaponids[weaponactive]].blooddrip += 5;
2993 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2995 if (whichtri == -1) {
2997 emit_sound_at(knifesheathesound, coords, 128.);
3003 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3005 emit_sound_at(knifedrawsound, coords, 128);
3008 if (victim && hasvictim) {
3009 XYZ footvel, footpoint;
3011 emit_sound_at(fleshstabremovesound, coords, 128.);
3014 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
3016 if (weapons[weaponids[weaponactive]].getType() == sword) {
3017 XYZ where, startpoint, endpoint, movepoint;
3018 float rotationpoint;
3021 where = weapons[weaponids[weaponactive]].position;
3022 where -= victim->coords;
3023 if (!victim->skeleton.free) {
3024 where = DoRotation(where, 0, -victim->yaw, 0);
3027 where = weapons[weaponids[weaponactive]].tippoint;
3028 where -= victim->coords;
3029 if (!victim->skeleton.free) {
3030 where = DoRotation(where, 0, -victim->yaw, 0);
3036 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
3037 footpoint += victim->coords;
3039 if (whichtri == -1) {
3040 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
3043 if (weapons[weaponids[weaponactive]].getType() == staff) {
3044 XYZ where, startpoint, endpoint, movepoint;
3045 float rotationpoint;
3048 where = weapons[weaponids[weaponactive]].position;
3049 where -= victim->coords;
3050 if (!victim->skeleton.free) {
3051 where = DoRotation(where, 0, -victim->yaw, 0);
3054 where = weapons[weaponids[weaponactive]].tippoint;
3055 where -= victim->coords;
3056 if (!victim->skeleton.free) {
3057 where = DoRotation(where, 0, -victim->yaw, 0);
3063 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
3064 footpoint += victim->coords;
3066 if (whichtri == -1) {
3067 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
3070 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
3072 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
3073 victim->skeleton.longdead = 0;
3074 victim->skeleton.free = 1;
3075 victim->skeleton.broken = 0;
3077 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3078 victim->skeleton.joints[i].velchange = 0;
3079 victim->skeleton.joints[i].locked = 0;
3080 //victim->skeleton.joints[i].velocity=0;
3086 Normalise(&relative);
3087 //victim->Puff(abdomen);
3089 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
3092 if (victim->bloodloss < victim->damagetolerance) {
3093 victim->bloodloss += 1000;
3097 victim->jointVel(abdomen) += relative * damagemult * 20;
3101 if (!hasvictim && onterrain) {
3102 weapons[weaponids[weaponactive]].bloody = 0;
3103 weapons[weaponids[weaponactive]].blooddrip = 0;
3107 if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3108 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
3117 if (!Tutorial::active) {
3118 emit_sound_at(heavyimpactsound, victim->coords, 128);
3123 relative = victim->coords - coords;
3125 Normalise(&relative);
3126 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3127 victim->skeleton.joints[i].velocity = relative * 30;
3129 victim->jointVel(head) += relative * damagemult * 150;
3131 victim->frameTarget = 0;
3132 victim->animTarget = staggerbackhardanim;
3133 victim->targetyaw = targetyaw + 180;
3135 victim->stunned = 1;
3138 victim->Puff(abdomen);
3139 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
3145 if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3146 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
3151 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
3152 if (!Tutorial::active) {
3153 emit_sound_at(thudsound, victim->coords);
3155 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
3156 if (!Tutorial::active) {
3157 emit_sound_at(whooshhitsound, victim->coords);
3160 if (!Tutorial::active) {
3161 emit_sound_at(heavyimpactsound, victim->coords);
3165 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight) {
3169 relative = victim->coords - coords;
3171 Normalise(&relative);
3173 Normalise(&relative);
3174 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3175 victim->skeleton.joints[i].velocity = relative * 5;
3177 victim->jointVel(abdomen) += relative * damagemult * 400;
3179 victim->frameTarget = 0;
3180 victim->animTarget = staggerbackhardanim;
3181 victim->targetyaw = targetyaw + 180;
3183 victim->stunned = 1;
3185 victim->Puff(abdomen);
3186 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
3192 if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3193 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3194 if (victim->id == 0) {
3197 emit_sound_at(landsound2, victim->coords);
3203 if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3204 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3205 if (victim->id == 0) {
3209 if (weaponactive != -1) {
3210 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3211 if (weapons[victim->weaponids[0]].getType() == staff) {
3212 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3214 if (weapons[weaponids[0]].getType() == staff) {
3215 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3218 emit_sound_at(swordstaffsound, victim->coords);
3220 emit_sound_at(metalhitsound, victim->coords);
3228 if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3229 if (weaponactive != -1) {
3232 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);
3234 weapons[weaponids[0]].thrown(aim * 50);
3237 weaponids[0] = weaponids[num_weapons];
3243 if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3245 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 && /*Animation::animations[victim->animTarget].height!=lowheight&&*/ victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
3247 if (!Tutorial::active) {
3248 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
3251 award_bonus(id, Slicebonus);
3252 if (!Tutorial::active) {
3253 emit_sound_at(knifeslicesound, victim->coords);
3255 //victim->jointVel(abdomen)+=relative*damagemult*200;
3256 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
3257 if (victim->id != 0 || difficulty == 2) {
3258 victim->frameTarget = 0;
3259 victim->animTarget = staggerbackhardanim;
3260 victim->targetyaw = targetyaw + 180;
3264 victim->lowreversaldelay = 0;
3265 victim->highreversaldelay = 0;
3266 if (aitype != playercontrolled) {
3267 weaponmissdelay = .6;
3270 if (!Tutorial::active) {
3271 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3272 weapons[weaponids[weaponactive]].bloody = 1;
3274 weapons[weaponids[weaponactive]].blooddrip += 3;
3277 XYZ footvel, footpoint;
3279 if (skeleton.free) {
3280 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3282 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3284 if (Tutorial::active) {
3285 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
3288 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
3290 footvel = DoRotation(facing, 0, 90, 0) * .8;
3291 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3292 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3293 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3294 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3296 victim->DoDamage(damagemult * 0);
3300 if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3301 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
3302 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
3303 award_bonus(id, Slashbonus);
3305 if (!Tutorial::active) {
3306 if (normaldotproduct(victim->facing, victim->coords - coords) < 0) {
3307 victim->DoBloodBig(2 / victim->armorhigh, 190);
3309 victim->DoBloodBig(2 / victim->armorhigh, 185);
3311 victim->deathbleeding = 1;
3312 emit_sound_at(swordslicesound, victim->coords);
3313 victim->frameTarget = 0;
3314 victim->animTarget = staggerbackhardanim;
3315 victim->targetyaw = targetyaw + 180;
3317 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3318 weapons[weaponids[weaponactive]].bloody = 1;
3320 weapons[weaponids[weaponactive]].blooddrip += 3;
3322 float bloodlossamount;
3323 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
3324 victim->bloodloss += bloodlossamount / victim->armorhigh;
3325 victim->DoDamage(damagemult * 0);
3327 XYZ footvel, footpoint;
3329 if (skeleton.free) {
3330 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3332 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3335 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3337 footvel = DoRotation(facing, 0, 90, 0) * .8;
3339 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3340 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3341 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3342 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3345 if (victim->weaponactive != -1) {
3346 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3347 if (weapons[victim->weaponids[0]].getType() == staff) {
3348 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3350 if (weapons[weaponids[0]].getType() == staff) {
3351 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3354 emit_sound_at(swordstaffsound, victim->coords);
3356 emit_sound_at(metalhitsound, victim->coords);
3361 victim->Puff(righthand);
3363 victim->frameTarget = 0;
3364 victim->animTarget = staggerbackhighanim;
3365 victim->targetyaw = targetyaw + 180;
3367 aim = DoRotation(facing, 0, 90, 0) * 21;
3369 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3370 victim->num_weapons--;
3371 if (victim->num_weapons) {
3372 victim->weaponids[0] = victim->weaponids[num_weapons];
3373 if (victim->weaponstuck == victim->num_weapons) {
3374 victim->weaponstuck = 0;
3377 victim->weaponactive = -1;
3378 for (unsigned i = 0; i < Person::players.size(); i++) {
3379 Person::players[i]->wentforweapon = 0;
3385 if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3386 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3387 if (!Tutorial::active) {
3388 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3393 if (Random() % 2 || creature == wolftype) {
3396 emit_sound_at(staffheadsound, victim->coords);
3400 relative = victim->coords - coords;
3402 Normalise(&relative);
3403 relative = DoRotation(relative, 0, 90, 0);
3405 Normalise(&relative);
3406 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3407 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3409 victim->jointVel(head) += relative * damagemult * 230;
3410 victim->jointVel(neck) += relative * damagemult * 230;
3412 if (!Tutorial::active) {
3413 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3415 award_bonus(id, solidhit, 30);
3420 if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3421 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3422 if (!Tutorial::active) {
3423 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3428 if (Random() % 2 || creature == wolftype) {
3431 emit_sound_at(staffheadsound, victim->coords);
3435 relative = victim->coords - coords;
3437 Normalise(&relative);
3438 relative = DoRotation(relative, 0, -90, 0);
3439 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3440 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3442 victim->jointVel(head) += relative * damagemult * 220;
3443 victim->jointVel(neck) += relative * damagemult * 220;
3445 if (!Tutorial::active) {
3446 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3448 award_bonus(id, solidhit, 60);
3453 if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3454 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3456 if (!Tutorial::active) {
3457 if (!victim->dead) {
3458 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3463 if (Random() % 2 || creature == wolftype) {
3466 emit_sound_at(staffbodysound, victim->coords);
3468 victim->skeleton.longdead = 0;
3469 victim->skeleton.free = 1;
3470 victim->skeleton.broken = 0;
3472 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3473 victim->skeleton.joints[i].velchange = 0;
3474 victim->skeleton.joints[i].locked = 0;
3475 //victim->skeleton.joints[i].velocity=0;
3482 Normalise(&relative);
3483 if (!victim->dead) {
3484 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3485 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3487 victim->jointVel(abdomen) += relative * damagemult * 40;
3490 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3491 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3494 victim->Puff(abdomen);
3495 if (!Tutorial::active) {
3496 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3498 if (!victim->dead) {
3499 award_bonus(id, solidhit, 40);
3505 if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3506 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3512 relative = victim->coords - coords;
3514 Normalise(&relative);
3518 if (Animation::animations[victim->animTarget].height == lowheight) {
3524 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3525 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3527 victim->jointVel(head) += relative * damagemult * 200;
3528 if (!Tutorial::active) {
3529 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3532 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3533 if (victim->howactive == typesleeping) {
3534 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3536 if (creature == wolftype) {
3537 emit_sound_at(clawslicesound, victim->coords, 128.);
3539 victim->DoBloodBig(2 / victim->armorhead, 175);
3542 if (victim->damage >= victim->damagetolerance) {
3545 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3546 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3548 victim->jointVel(abdomen) += relative * damagemult * 200;
3549 victim->frameTarget = 0;
3550 victim->animTarget = staggerbackhighanim;
3551 victim->targetyaw = targetyaw + 180;
3553 if (!Tutorial::active) {
3554 emit_sound_at(landsound2, victim->coords, 128.);
3556 victim->Puff(abdomen);
3557 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3558 if (creature == wolftype) {
3559 emit_sound_at(clawslicesound, victim->coords, 128.);
3561 victim->DoBloodBig(2 / victim->armorhigh, 170);
3567 if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3568 if ((victim->animTarget != jumpupanim) &&
3569 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3570 (victim != this->shared_from_this())) {
3575 if (!Tutorial::active) {
3576 emit_sound_at(landsound2, victim->coords, 128.);
3579 relative = victim->coords - coords;
3581 Normalise(&relative);
3583 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3586 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3587 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3589 relative = DoRotation(relative, 0, -90, 0);
3591 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3592 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) {
3593 victim->skeleton.joints[i].velocity = relative * 80;
3596 victim->Puff(rightankle);
3597 victim->Puff(leftankle);
3598 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3600 if (victim->damage >= victim->damagetolerance) {
3603 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3604 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3606 relative = DoRotation(relative, 0, -90, 0);
3607 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3608 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) {
3609 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3612 victim->jointVel(abdomen) += relative * damagemult * 200;
3613 victim->frameTarget = 0;
3614 victim->animTarget = staggerbackhighanim;
3615 victim->targetyaw = targetyaw + 180;
3617 if (!Tutorial::active) {
3618 emit_sound_at(landsound2, victim->coords, 128.);
3620 victim->Puff(abdomen);
3621 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3628 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3629 if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3638 if (!Tutorial::active) {
3639 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3641 if (creature == wolftype) {
3642 emit_sound_at(clawslicesound, victim->coords, 128);
3644 victim->DoBloodBig(2 / victim->armorhigh, 170);
3648 relative = victim->coords - oldcoords;
3650 Normalise(&relative);
3651 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3652 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3654 victim->jointVel(abdomen) += relative * damagemult * 200;
3655 victim->Puff(abdomen);
3656 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3658 award_bonus(id, Reversal);
3661 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3662 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3663 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3664 takeWeapon(victim->weaponids[victim->weaponactive]);
3665 victim->num_weapons--;
3666 if (victim->num_weapons > 0) {
3667 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3669 victim->weaponactive = -1;
3674 if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3683 emit_sound_at(whooshhitsound, victim->coords, 128.);
3686 relative = victim->coords - oldcoords;
3688 Normalise(&relative);
3689 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3690 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3692 victim->jointVel(abdomen) += relative * damagemult * 200;
3694 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3697 if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3707 award_bonus(id, staffreversebonus);
3709 if (!Tutorial::active) {
3710 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3713 award_bonus(id, staffreversebonus); // Huh, again?
3716 relative = victim->coords - oldcoords;
3718 Normalise(&relative);
3719 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3720 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3722 victim->jointVel(abdomen) += relative * damagemult * 200;
3724 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3727 if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3733 Normalise(&relative);
3735 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3736 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3738 victim->jointVel(lefthand) *= .1;
3739 victim->jointVel(leftwrist) *= .2;
3740 victim->jointVel(leftelbow) *= .5;
3741 victim->jointVel(leftshoulder) *= .7;
3742 victim->jointVel(righthand) *= .1;
3743 victim->jointVel(rightwrist) *= .2;
3744 victim->jointVel(rightelbow) *= .5;
3745 victim->jointVel(rightshoulder) *= .7;
3747 victim->Puff(abdomen);
3748 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3750 award_bonus(id, Reversal);
3754 if (weaponactive != -1 || creature == wolftype) {
3757 if (creature == rabbittype && weaponactive != -1) {
3758 if (weapons[weaponids[0]].getType() == staff) {
3763 if (weaponactive != -1) {
3764 victim->DoBloodBig(2 / victim->armorhigh, 225);
3765 emit_sound_at(knifeslicesound, victim->coords);
3766 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3767 weapons[weaponids[weaponactive]].bloody = 1;
3769 weapons[weaponids[weaponactive]].blooddrip += 3;
3771 if (weaponactive == -1 && creature == wolftype) {
3772 emit_sound_at(clawslicesound, victim->coords, 128.);
3774 victim->DoBloodBig(2 / victim->armorhigh, 175);
3779 if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3785 Normalise(&relative);
3787 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3788 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3790 victim->jointVel(lefthand) *= .1 - 1;
3791 victim->jointVel(leftwrist) *= .2 - 1;
3792 victim->jointVel(leftelbow) *= .5 - 1;
3793 victim->jointVel(leftshoulder) *= .7 - 1;
3794 victim->jointVel(righthand) *= .1 - 1;
3795 victim->jointVel(rightwrist) *= .2 - 1;
3796 victim->jointVel(rightelbow) *= .5 - 1;
3797 victim->jointVel(rightshoulder) *= .7 - 1;
3799 award_bonus(id, swordreversebonus);
3802 if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3811 if (!Tutorial::active) {
3812 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3816 relative = victim->coords - oldcoords;
3818 Normalise(&relative);
3819 relative = DoRotation(relative, 0, -90, 0);
3820 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3821 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3823 victim->jointVel(abdomen) += relative * damagemult * 200;
3824 victim->Puff(abdomen);
3825 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3827 award_bonus(id, Reversal);
3830 if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3833 victim->skeleton.spinny = 0;
3835 relative = facing * -1;
3837 Normalise(&relative);
3838 if (victim->id == 0) {
3841 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3842 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3844 victim->damage = victim->damagetolerance;
3845 victim->permanentdamage = victim->damagetolerance - 1;
3848 if (weaponactive != -1 || creature == wolftype) {
3851 if (creature == rabbittype && weaponactive != -1) {
3852 if (weapons[weaponids[0]].getType() == staff) {
3857 if (weaponactive != -1) {
3858 victim->DoBloodBig(200, 225);
3859 emit_sound_at(knifeslicesound, victim->coords);
3861 weapons[weaponids[weaponactive]].bloody = 2;
3863 weapons[weaponids[weaponactive]].blooddrip += 5;
3866 if (creature == wolftype && weaponactive == -1) {
3867 emit_sound_at(clawslicesound, victim->coords, 128.);
3869 victim->DoBloodBig(2, 175);
3872 award_bonus(id, spinecrusher);
3875 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3876 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3878 if (animTarget == knifefollowanim) {
3879 victim->DoBloodBig(200, 210);
3881 if (animTarget == knifesneakattackanim) {
3882 XYZ footvel, footpoint;
3884 footpoint = weapons[weaponids[0]].tippoint;
3886 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3888 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3889 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3890 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3891 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3892 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3893 victim->DoBloodBig(200, 195);
3894 award_bonus(id, tracheotomy);
3896 if (animTarget == knifefollowanim) {
3897 award_bonus(id, Stabbonus);
3898 XYZ footvel, footpoint;
3900 footpoint = weapons[weaponids[0]].tippoint;
3902 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3904 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3905 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3906 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3907 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3908 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3910 victim->bloodloss += 10000;
3911 victim->velocity = 0;
3912 emit_sound_at(fleshstabsound, victim->coords);
3914 weapons[weaponids[weaponactive]].bloody = 2;
3916 weapons[weaponids[weaponactive]].blooddrip += 5;
3920 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3922 victim->velocity = 0;
3923 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3924 victim->skeleton.joints[i].velocity = 0;
3926 if (animTarget == knifefollowanim) {
3928 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3929 victim->skeleton.joints[i].velocity = 0;
3932 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3933 emit_sound_at(fleshstabremovesound, victim->coords);
3935 weapons[weaponids[weaponactive]].bloody = 2;
3937 weapons[weaponids[weaponactive]].blooddrip += 5;
3939 XYZ footvel, footpoint;
3941 footpoint = weapons[weaponids[0]].tippoint;
3943 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3945 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3946 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3947 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3948 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3949 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3953 if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3954 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3955 award_bonus(id, backstab);
3959 XYZ footvel, footpoint;
3961 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3963 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3965 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3966 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3967 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3968 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3969 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3970 victim->DoBloodBig(200, 180);
3971 victim->DoBloodBig(200, 215);
3972 victim->bloodloss += 10000;
3973 victim->velocity = 0;
3974 emit_sound_at(fleshstabsound, victim->coords);
3976 weapons[weaponids[weaponactive]].bloody = 2;
3978 weapons[weaponids[weaponactive]].blooddrip += 5;
3982 if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3984 victim->velocity = 0;
3985 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3986 victim->skeleton.joints[i].velocity = 0;
3988 if (weaponactive != -1) {
3989 emit_sound_at(fleshstabremovesound, victim->coords);
3991 weapons[weaponids[weaponactive]].bloody = 2;
3993 weapons[weaponids[weaponactive]].blooddrip += 5;
3995 XYZ footvel, footpoint;
3997 footpoint = weapons[weaponids[0]].tippoint;
3999 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
4001 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
4002 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
4003 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
4004 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
4005 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
4009 if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
4018 if (weaponactive == -1) {
4019 if (!Tutorial::active) {
4020 emit_sound_at(heavyimpactsound, victim->coords, 128.);
4025 if (weaponactive != -1 || creature == wolftype) {
4028 if (creature == rabbittype && weaponactive != -1) {
4029 if (weapons[weaponids[0]].getType() == staff) {
4034 if (weaponactive != -1) {
4035 victim->DoBloodBig(2 / victim->armorhead, 225);
4036 emit_sound_at(knifeslicesound, victim->coords);
4037 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
4038 weapons[weaponids[weaponactive]].bloody = 1;
4040 weapons[weaponids[weaponactive]].blooddrip += 3;
4042 if (weaponactive == -1 && creature == wolftype) {
4043 emit_sound_at(clawslicesound, victim->coords, 128.);
4045 victim->DoBloodBig(2 / victim->armorhead, 175);
4049 award_bonus(id, Reversal);
4054 relative = facing * -1;
4056 Normalise(&relative);
4057 relative = DoRotation(relative, 0, 90, 0);
4059 Normalise(&relative);
4060 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
4061 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
4063 victim->jointVel(head) += relative * damagemult * 200;
4064 if (victim->damage < victim->damagetolerance - 100) {
4065 victim->velocity = relative * 200;
4067 victim->DoDamage(damagemult * 100 / victim->protectionhead);
4068 victim->velocity = 0;
4071 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))) {
4075 relative = facing * -1;
4077 Normalise(&relative);
4078 relative = DoRotation(relative, 0, 90, 0);
4080 Normalise(&relative);
4081 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
4082 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
4084 victim->jointVel(head) += relative * damagemult * 200;
4087 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim)) {
4088 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
4089 award_bonus(id, reverseko);
4095 if (frameTarget > int(Animation::animations[animCurrent].frames.size()) - 1) {
4098 animTarget = getIdle();
4099 FootLand(leftfoot, 1);
4100 FootLand(rightfoot, 1);
4102 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
4103 animTarget = rollanim;
4105 emit_sound_at(movewhooshsound, coords, 128.);
4107 if (animCurrent == staggerbackhighanim) {
4108 animTarget = getIdle();
4110 if (animCurrent == staggerbackhardanim) {
4111 animTarget = getIdle();
4113 if (animCurrent == removeknifeanim) {
4114 animTarget = getIdle();
4116 if (animCurrent == crouchremoveknifeanim) {
4117 animTarget = getCrouch();
4119 if (animCurrent == backhandspringanim) {
4120 animTarget = getIdle();
4122 if (animCurrent == dodgebackanim) {
4123 animTarget = getIdle();
4125 if (animCurrent == drawleftanim) {
4126 animTarget = getIdle();
4128 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
4129 animTarget = getIdle();
4130 if (animCurrent == crouchdrawrightanim) {
4131 animTarget = getCrouch();
4133 if (weaponactive == -1) {
4135 } else if (weaponactive == 0) {
4137 if (num_weapons == 2) {
4139 buffer = weaponids[0];
4140 weaponids[0] = weaponids[1];
4141 weaponids[1] = buffer;
4145 if (weaponactive == -1) {
4146 emit_sound_at(knifesheathesound, coords, 128.);
4148 if (weaponactive != -1) {
4149 emit_sound_at(knifedrawsound, coords, 128.);
4152 if (animCurrent == rollanim) {
4153 animTarget = getCrouch();
4154 FootLand(leftfoot, 1);
4155 FootLand(rightfoot, 1);
4158 if (animTarget == walljumprightkickanim) {
4161 if (animTarget == walljumpleftkickanim) {
4164 animTarget = jumpdownanim;
4166 if (animCurrent == climbanim) {
4167 animTarget = getCrouch();
4169 coords += facing * .1;
4170 if (!isnormal(coords.x)) {
4181 if (animTarget == rabbitkickreversalanim) {
4182 animTarget = getCrouch();
4185 if (animTarget == jumpreversalanim) {
4186 animTarget = getCrouch();
4189 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
4190 if (attackkeydown && animTarget != walljumpfrontanim) {
4192 float closestdist = -1;
4194 if (Person::players.size() > 1) {
4195 for (unsigned i = 0; i < Person::players.size(); i++) {
4196 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4197 distance = distsq(&Person::players[i]->coords, &coords);
4198 if (closestdist == -1 || distance < closestdist) {
4199 closestdist = distance;
4205 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4206 victim = Person::players[closest];
4207 animTarget = walljumprightkickanim;
4209 XYZ rotatetarget = victim->coords - coords;
4210 Normalise(&rotatetarget);
4211 yaw = -asin(0 - rotatetarget.x);
4213 if (rotatetarget.z < 0) {
4216 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4217 velocity = (victim->coords - coords) * 4;
4222 if (animTarget == walljumpbackanim) {
4223 animTarget = backflipanim;
4225 velocity = facing * -8;
4228 resume_stream(whooshsound);
4231 if (animTarget == walljumprightanim) {
4232 animTarget = rightflipanim;
4236 velocity = DoRotation(facing, 0, 30, 0) * -8;
4239 if (animTarget == walljumpfrontanim) {
4240 animTarget = frontflipanim;
4244 velocity = facing * 8;
4248 resume_stream(whooshsound);
4251 if (animTarget == walljumpleftanim) {
4252 if (attackkeydown) {
4254 float closestdist = -1;
4256 if (Person::players.size() > 1) {
4257 for (unsigned i = 0; i < Person::players.size(); i++) {
4258 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4259 distance = distsq(&Person::players[i]->coords, &coords);
4260 if (closestdist == -1 || distance < closestdist) {
4261 closestdist = distance;
4267 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4268 victim = Person::players[closest];
4269 animTarget = walljumpleftkickanim;
4271 XYZ rotatetarget = victim->coords - coords;
4272 Normalise(&rotatetarget);
4273 yaw = -asin(0 - rotatetarget.x);
4275 if (rotatetarget.z < 0) {
4278 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4279 velocity = (victim->coords - coords) * 4;
4284 if (animTarget != walljumpleftkickanim) {
4285 animTarget = leftflipanim;
4289 velocity = DoRotation(facing, 0, -30, 0) * -8;
4293 resume_stream(whooshsound);
4296 if (animTarget == sneakattackanim) {
4297 animCurrent = getCrouch();
4298 animTarget = getCrouch();
4305 transspeed = 1000000;
4306 targetheadyaw += 180;
4307 coords -= facing * .7;
4309 coords.y = terrain.getHeight(coords.x, coords.z);
4314 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
4315 animTarget = getIdle();
4318 coords.y = terrain.getHeight(coords.x, coords.z);
4323 if (animCurrent == knifefollowanim) {
4324 animTarget = getIdle();
4327 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
4328 float ycoords = oldcoords.y;
4329 animTarget = getStop();
4334 transspeed = 1000000;
4335 targetheadyaw += 180;
4336 if (!isnormal(coords.x)) {
4339 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim) {
4340 oldcoords = coords + facing * .5;
4341 } else if (animCurrent == sweepreversalanim) {
4342 oldcoords = coords + facing * 1.1;
4343 } else if (animCurrent == upunchreversalanim) {
4344 oldcoords = coords + facing * 1.5;
4347 targetheadyaw += 180;
4350 } else if (animCurrent == knifeslashreversalanim) {
4351 oldcoords = coords + facing * .5;
4354 targetheadyaw += 90;
4357 } else if (animCurrent == staffspinhitreversalanim) {
4360 targetheadyaw += 180;
4365 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
4367 oldcoords.y = ycoords;
4369 currentoffset = coords - oldcoords;
4375 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4380 if (Animation::animations[animTarget].attack == reversed) {
4382 if (animTarget == sweepreversedanim) {
4385 animTarget = backhandspringanim;
4387 emit_sound_at(landsound, coords, 128);
4389 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4390 animTarget = rollanim;
4393 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4394 coords.y = oldcoords.y;
4396 if (animCurrent == knifeslashreversedanim) {
4397 animTarget = rollanim;
4402 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4403 coords.y = oldcoords.y;
4407 animTarget = jumpdownanim;
4410 animTarget = getIdle();
4412 if (wasLandhard()) {
4413 animTarget = getIdle();
4415 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4416 animTarget = getIdle();
4418 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4419 coords.y = oldcoords.y;
4420 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4421 targetoffset.y = coords.y;
4423 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4425 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4426 currentoffset.y -= (coords.y - targetoffset.y);
4427 coords.y = targetoffset.y;
4429 normalsupdatedelay = 0;
4431 if (animCurrent == upunchanim) {
4432 animTarget = getStop();
4433 normalsupdatedelay = 0;
4436 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4440 if (num_weapons > 0) {
4441 if (weapons[0].getType() == staff) {
4450 rabbitkickragdoll = 1;
4452 if (animCurrent == rabbitkickreversedanim) {
4458 skeleton.spinny = 0;
4459 SolidHitBonus(!id); // FIXME: tricky id
4463 animTarget = rollanim;
4466 pause_sound(whooshsound);
4471 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4475 skeleton.spinny = 0;
4477 if (animCurrent == jumpreversedanim) {
4483 skeleton.spinny = 0;
4484 SolidHitBonus(!id); // FIXME: tricky id
4488 animTarget = rollanim;
4489 coords += facing * 2;
4491 pause_sound(whooshsound);
4497 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) {
4498 animTarget = getupfromfrontanim;
4500 } else if (Animation::animations[animCurrent].attack == normalattack) {
4501 animTarget = getIdle();
4504 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4505 animTarget = blockhighleftstrikeanim;
4507 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4508 animTarget = getIdle();
4511 if (animCurrent == spinkickanim && victim->skeleton.free) {
4512 if (creature == rabbittype) {
4513 animTarget = fightidleanim;
4519 if (isIdle() && !wasIdle()) {
4520 normalsupdatedelay = 0;
4523 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4524 animTarget = jumpdownanim;
4527 if (!skeleton.free) {
4529 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4530 if (!isRun() || !wasRun()) {
4531 if (targetFrame().speed > currentFrame().speed) {
4532 target += multiplier * targetFrame().speed * speed * 2;
4534 if (targetFrame().speed <= currentFrame().speed) {
4535 target += multiplier * currentFrame().speed * speed * 2;
4538 if (isRun() && wasRun()) {
4540 tempspeed = velspeed;
4541 if (tempspeed < 10 * speedmult) {
4542 tempspeed = 10 * speedmult;
4544 /* FIXME - mixed of target and current here, is that intended? */
4545 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4547 } else if (transspeed) {
4548 target += multiplier * transspeed * speed * 2;
4550 if (!isRun() || !wasRun()) {
4551 if (targetFrame().speed > currentFrame().speed) {
4552 target += multiplier * targetFrame().speed * 2;
4554 if (targetFrame().speed <= currentFrame().speed) {
4555 target += multiplier * currentFrame().speed * 2;
4560 if (animCurrent != animTarget) {
4561 target = (target + oldtarget) / 2;
4565 frameCurrent = frameTarget;
4569 rot = targetrot * target;
4570 yaw += rot - oldrot;
4576 if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
4577 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4579 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4581 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4582 skeleton.joints[i].position = currentFrame().joints[i].position;
4585 skeleton.FindForwards();
4587 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4588 if (skeleton.muscles[i].visible) {
4589 skeleton.FindRotationMuscle(i, animTarget);
4592 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4593 if (skeleton.muscles[i].visible) {
4594 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4595 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4597 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4598 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4600 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4601 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4607 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4608 skeleton.joints[i].position = targetFrame().joints[i].position;
4611 skeleton.FindForwards();
4613 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4614 if (skeleton.muscles[i].visible) {
4615 skeleton.FindRotationMuscle(i, animTarget);
4618 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4619 if (skeleton.muscles[i].visible) {
4620 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4621 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4623 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4624 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4626 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4627 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4629 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) {
4630 skeleton.muscles[i].newrotate3 -= 360;
4632 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) {
4633 skeleton.muscles[i].newrotate3 += 360;
4635 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) {
4636 skeleton.muscles[i].newrotate2 -= 360;
4638 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) {
4639 skeleton.muscles[i].newrotate2 += 360;
4641 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) {
4642 skeleton.muscles[i].newrotate1 -= 360;
4644 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) {
4645 skeleton.muscles[i].newrotate1 += 360;
4651 oldanimCurrent = animCurrent;
4652 oldanimTarget = animTarget;
4653 oldframeTarget = frameTarget;
4654 oldframeCurrent = frameCurrent;
4656 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4657 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target - skeleton.joints[i].position) / multiplier;
4658 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target;
4660 offset = currentoffset * (1 - target) + targetoffset * target;
4661 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4662 if (skeleton.muscles[i].visible) {
4663 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * target;
4664 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * target;
4665 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * target;
4670 if (isLanding() && landhard) {
4674 animTarget = getLandhard();
4687 void Person::DoStuff()
4689 static XYZ terrainnormal;
4690 static XYZ flatfacing;
4691 static XYZ flatvelocity;
4692 static float flatvelspeed;
4693 static int bloodsize;
4694 static int startx, starty, endx, endy;
4695 static GLubyte color;
4696 static XYZ bloodvel;
4698 onfiredelay -= multiplier;
4699 if (onfiredelay < 0 && onfire) {
4700 if (Random() % 2 == 0) {
4706 crouchkeydowntime += multiplier;
4707 if (!crouchkeydown) {
4708 crouchkeydowntime = 0;
4710 jumpkeydowntime += multiplier;
4711 if (!jumpkeydown && skeleton.free) {
4712 jumpkeydowntime = 0;
4715 if (hostile || damage > 0 || bloodloss > 0) {
4719 if (isIdle() || isRun()) {
4723 if (num_weapons == 1 && weaponactive != -1) {
4728 blooddimamount -= multiplier * .3;
4730 speechdelay -= multiplier;
4731 texupdatedelay -= multiplier;
4732 interestdelay -= multiplier;
4733 flamedelay -= multiplier;
4734 parriedrecently -= multiplier;
4736 victim = this->shared_from_this();
4741 speed = 1.1 * speedmult;
4743 speed = 1.0 * speedmult;
4745 if (!skeleton.free) {
4746 rabbitkickragdoll = 0;
4751 if (id != 0 && (creature == rabbittype || difficulty != 2)) {
4754 if (id != 0 && creature == wolftype && difficulty == 2) {
4756 if (aitype != passivetype) {
4758 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) {
4765 if (animTarget == wolfrunninganim && !superruntoggle) {
4766 animTarget = getRun();
4770 if (weaponactive == -1 && num_weapons > 0) {
4771 if (weapons[weaponids[0]].getType() == staff) {
4777 burnt += multiplier;
4782 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4784 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4791 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
4792 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4796 while (flamedelay < 0 && onfire) {
4798 int howmany = fabs(Random() % (skeleton.joints.size()));
4799 if (skeleton.free) {
4800 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4801 flatfacing = skeleton.joints[howmany].position * scale + coords;
4803 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4804 flatvelocity = (coords - oldcoords) / multiplier / 2;
4806 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4809 while (flamedelay < 0 && !onfire && Tutorial::active && id != 0) {
4811 int howmany = fabs(Random() % (skeleton.joints.size()));
4812 if (skeleton.free) {
4813 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4814 flatfacing = skeleton.joints[howmany].position * scale + coords;
4816 flatvelocity = (coords - oldcoords) / multiplier / 2;
4817 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4819 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4823 bleeding -= multiplier * .3;
4824 if (bloodtoggle == 2) {
4825 skeleton.drawmodel.textureptr.bind();
4826 if ((bleeding <= 0) && (detail != 2)) {
4832 if (neckspurtamount > 0) {
4833 neckspurtamount -= multiplier;
4834 neckspurtdelay -= multiplier * 3;
4835 neckspurtparticledelay -= multiplier * 3;
4836 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4839 if (skeleton.free) {
4840 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4841 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4842 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4844 bloodvel.z = 5 * neckspurtamount;
4845 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4846 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4847 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4849 neckspurtparticledelay = .05;
4851 if (neckspurtdelay < 0) {
4856 if (deathbleeding > 0 && dead != 2) {
4857 if (deathbleeding < 5) {
4858 bleeddelay -= deathbleeding * multiplier / 4;
4860 bleeddelay -= 5 * multiplier / 4;
4862 if (bleeddelay < 0 && bloodtoggle) {
4867 if (skeleton.free) {
4868 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4869 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4871 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4872 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4876 bloodloss += deathbleeding * multiplier * 80;
4877 deathbleeding -= multiplier * 1.6;
4878 if (deathbleeding < 0) {
4881 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4882 if (weaponactive != -1) {
4883 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4884 weapons[weaponids[0]].velocity.x += .01;
4887 weaponids[0] = weaponids[num_weapons];
4888 if (weaponstuck == num_weapons) {
4893 for (unsigned i = 0; i < Person::players.size(); i++) {
4894 Person::players[i]->wentforweapon = 0;
4902 if (!dead && creature == wolftype) {
4903 award_bonus(0, Wolfbonus);
4906 if (animTarget == knifefollowedanim && !skeleton.free) {
4907 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4908 skeleton.joints[i].velocity = 0;
4909 skeleton.joints[i].velocity.y = -2;
4912 if (id != 0 && unconscioustime > .1) {
4920 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4921 texupdatedelay = .12;
4923 bloodsize = 5 - realtexdetail;
4927 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4928 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4929 endx = startx + bloodsize;
4930 endy = starty + bloodsize;
4940 if (endx > skeleton.skinsize - 1) {
4941 endx = skeleton.skinsize - 1;
4944 if (endy > skeleton.skinsize - 1) {
4945 endy = skeleton.skinsize - 1;
4948 if (endx < startx) {
4951 if (endy < starty) {
4955 for (int i = startx; i < endx; i++) {
4956 for (int j = starty; j < endy; j++) {
4957 if (Random() % 2 == 0) {
4958 color = Random() % 85 + 170;
4959 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2) {
4960 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4962 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4963 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4968 skeleton.drawmodel.textureptr.bind();
4972 if (skeleton.free) {
4973 bleedx += 4 * direction / realtexdetail;
4975 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4977 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4980 bleedy -= 4 / realtexdetail;
4982 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4984 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4989 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4990 righthandmorphness = targetrighthandmorphness;
4991 righthandmorphstart = righthandmorphend;
4992 } else if (righthandmorphness > targetrighthandmorphness) {
4993 righthandmorphness -= multiplier * 4;
4994 } else if (righthandmorphness < targetrighthandmorphness) {
4995 righthandmorphness += multiplier * 4;
4998 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4999 lefthandmorphness = targetlefthandmorphness;
5000 lefthandmorphstart = lefthandmorphend;
5001 } else if (lefthandmorphness > targetlefthandmorphness) {
5002 lefthandmorphness -= multiplier * 4;
5003 } else if (lefthandmorphness < targetlefthandmorphness) {
5004 lefthandmorphness += multiplier * 4;
5007 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
5008 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
5009 tailmorphness = targettailmorphness;
5010 tailmorphstart = tailmorphend;
5011 } else if (tailmorphness > targettailmorphness) {
5012 tailmorphness -= multiplier * 10;
5013 } else if (tailmorphness < targettailmorphness) {
5014 tailmorphness += multiplier * 10;
5018 if (creature == wolftype) {
5019 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
5020 tailmorphness = targettailmorphness;
5021 tailmorphstart = tailmorphend;
5022 } else if (tailmorphness > targettailmorphness) {
5023 tailmorphness -= multiplier * 2;
5024 } else if (tailmorphness < targettailmorphness) {
5025 tailmorphness += multiplier * 2;
5029 if (headmorphend == 3 || headmorphstart == 3) {
5030 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
5031 headmorphness = targetheadmorphness;
5032 headmorphstart = headmorphend;
5033 } else if (headmorphness > targetheadmorphness) {
5034 headmorphness -= multiplier * 7;
5035 } else if (headmorphness < targetheadmorphness) {
5036 headmorphness += multiplier * 7;
5038 } else if (headmorphend == 5 || headmorphstart == 5) {
5039 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
5040 headmorphness = targetheadmorphness;
5041 headmorphstart = headmorphend;
5042 } else if (headmorphness > targetheadmorphness) {
5043 headmorphness -= multiplier * 10;
5044 } else if (headmorphness < targetheadmorphness) {
5045 headmorphness += multiplier * 10;
5048 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
5049 headmorphness = targetheadmorphness;
5050 headmorphstart = headmorphend;
5051 } else if (headmorphness > targetheadmorphness) {
5052 headmorphness -= multiplier * 4;
5053 } else if (headmorphness < targetheadmorphness) {
5054 headmorphness += multiplier * 4;
5058 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
5059 chestmorphness = targetchestmorphness;
5060 chestmorphstart = chestmorphend;
5061 } else if (chestmorphness > targetchestmorphness) {
5062 chestmorphness -= multiplier;
5063 } else if (chestmorphness < targetchestmorphness) {
5064 chestmorphness += multiplier;
5067 if (dead != 2 && howactive <= typesleeping) {
5068 if (chestmorphstart == 0 && chestmorphend == 0) {
5070 targetchestmorphness = 1;
5073 if (chestmorphstart != 0 && chestmorphend != 0) {
5075 targetchestmorphness = 1;
5077 if (environment == snowyenvironment) {
5080 if (skeleton.free) {
5081 footvel = skeleton.specialforward[0] * -1;
5082 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
5084 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
5085 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
5087 if (animTarget == sleepanim) {
5088 footvel = DoRotation(footvel, 0, 90, 0);
5090 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
5094 if (!dead && howactive < typesleeping) {
5095 blinkdelay -= multiplier * 2;
5096 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
5098 targetheadmorphness = 1;
5100 blinkdelay = (float)(abs(Random() % 40)) / 5;
5102 if (headmorphstart == 3 && headmorphend == 3) {
5104 targetheadmorphness = 1;
5109 twitchdelay -= multiplier * 1.5;
5110 if (animTarget != hurtidleanim) {
5111 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
5113 targetheadmorphness = 1;
5115 twitchdelay = (float)(abs(Random() % 40)) / 5;
5117 if (headmorphstart == 5 && headmorphend == 5) {
5119 targetheadmorphness = 1;
5123 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
5124 twitchdelay3 -= multiplier * 1;
5125 if (Random() % 2 == 0) {
5126 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
5127 righthandmorphness = 0;
5128 targetrighthandmorphness = 1;
5129 righthandmorphend = 1;
5130 if (Random() % 2 == 0) {
5131 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
5134 if (righthandmorphstart == 1 && righthandmorphend == 1) {
5135 righthandmorphness = 0;
5136 targetrighthandmorphness = 1;
5137 righthandmorphend = 0;
5140 if (Random() % 2 == 0) {
5141 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
5142 lefthandmorphness = 0;
5143 targetlefthandmorphness = 1;
5144 lefthandmorphend = 1;
5145 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
5147 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
5148 lefthandmorphness = 0;
5149 targetlefthandmorphness = 1;
5150 lefthandmorphend = 0;
5156 if (creature == rabbittype) {
5157 if (howactive < typesleeping) {
5158 twitchdelay2 -= multiplier * 1.5;
5160 twitchdelay2 -= multiplier * 0.5;
5162 if (howactive <= typesleeping) {
5163 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
5165 targettailmorphness = 1;
5167 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
5169 if (tailmorphstart == 1 && tailmorphend == 1) {
5171 targettailmorphness = 1;
5174 if (tailmorphstart == 2 && tailmorphend == 2) {
5176 targettailmorphness = 1;
5183 if (creature == wolftype) {
5184 twitchdelay2 -= multiplier * 1.5;
5185 if (tailmorphend != 0) {
5186 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
5188 targettailmorphness = 1;
5193 if (tailmorphend != 5) {
5194 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
5196 targettailmorphness = 1;
5201 if (twitchdelay2 <= 0) {
5202 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
5204 targettailmorphness = 1;
5207 if (tailmorphstart == 1 && tailmorphend == 1) {
5209 targettailmorphness = 1;
5212 if (tailmorphstart == 2 && tailmorphend == 2) {
5214 targettailmorphness = 1;
5217 if (tailmorphstart == 3 && tailmorphend == 3) {
5219 targettailmorphness = 1;
5222 if (tailmorphstart == 4 && tailmorphend == 4) {
5224 targettailmorphness = 1;
5231 unconscioustime = 0;
5234 if (dead == 1 || howactive == typesleeping) {
5235 unconscioustime += multiplier;
5236 //If unconscious, close eyes and mouth
5237 if (righthandmorphend != 0) {
5238 righthandmorphness = 0;
5240 righthandmorphend = 0;
5241 targetrighthandmorphness = 1;
5243 if (lefthandmorphend != 0) {
5244 lefthandmorphness = 0;
5246 lefthandmorphend = 0;
5247 targetlefthandmorphness = 1;
5249 if (headmorphend != 3 && headmorphend != 5) {
5253 targetheadmorphness = 1;
5256 if (howactive > typesleeping) {
5259 if (bloodtoggle && !bled) {
5260 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5261 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5262 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5263 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5267 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5273 if (dead == 2 || howactive > typesleeping) {
5274 //If dead, open mouth and hands
5275 if (righthandmorphend != 0) {
5276 righthandmorphness = 0;
5278 righthandmorphend = 0;
5279 targetrighthandmorphness = 1;
5281 if (lefthandmorphend != 0) {
5282 lefthandmorphness = 0;
5284 lefthandmorphend = 0;
5285 targetlefthandmorphness = 1;
5287 if (headmorphend != 2) {
5291 targetheadmorphness = 1;
5294 if (stunned > 0 && !dead && headmorphend != 2) {
5295 if (headmorphend != 4) {
5299 targetheadmorphness = 1;
5302 if (damage > damagetolerance && !dead) {
5305 unconscioustime = 0;
5307 if (creature == wolftype) {
5308 award_bonus(0, Wolfbonus);
5313 if (weaponactive != -1) {
5314 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5315 weapons[weaponids[0]].velocity.x += .01;
5318 weaponids[0] = weaponids[num_weapons];
5319 if (weaponstuck == num_weapons) {
5324 for (unsigned i = 0; i < Person::players.size(); i++) {
5325 Person::players[i]->wentforweapon = 0;
5329 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
5338 damage -= multiplier * 13;
5339 permanentdamage -= multiplier * 4;
5340 if (isIdle() || isCrouch()) {
5341 permanentdamage -= multiplier * 4;
5347 if (permanentdamage < 0) {
5348 permanentdamage = 0;
5350 if (superpermanentdamage < 0) {
5351 superpermanentdamage = 0;
5353 if (permanentdamage < superpermanentdamage) {
5354 permanentdamage = superpermanentdamage;
5356 if (damage < permanentdamage) {
5357 damage = permanentdamage;
5359 if (dead == 1 && damage < damagetolerance) {
5363 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5364 skeleton.joints[i].velocity = 0;
5367 if (permanentdamage > damagetolerance && dead != 2) {
5370 if (weaponactive != -1) {
5371 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5372 weapons[weaponids[0]].velocity.x += .01;
5375 weaponids[0] = weaponids[num_weapons];
5376 if (weaponstuck == num_weapons) {
5381 for (unsigned i = 0; i < Person::players.size(); i++) {
5382 Person::players[i]->wentforweapon = 0;
5388 if (!dead && creature == wolftype) {
5389 award_bonus(0, Wolfbonus);
5392 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance) {
5393 award_bonus(id, touchofdeath);
5395 if (id != 0 && unconscioustime > .1) {
5403 emit_sound_at(breaksound, coords);
5406 if (skeleton.free == 1) {
5408 pause_sound(whooshsound);
5412 //If knocked over, open hands and close mouth
5413 if (righthandmorphend != 0) {
5414 righthandmorphness = 0;
5416 righthandmorphend = 0;
5417 targetrighthandmorphness = 1;
5419 if (lefthandmorphend != 0) {
5420 lefthandmorphness = 0;
5422 lefthandmorphend = 0;
5423 targetlefthandmorphness = 1;
5425 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
5426 if (headmorphend != 0) {
5430 targetheadmorphness = 1;
5434 skeleton.DoGravity(&scale);
5436 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
5437 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1)) {
5438 award_bonus(id, deepimpact);
5440 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5444 if (!skeleton.joints.empty()) {
5445 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5446 average += skeleton.joints[j].position;
5448 average /= skeleton.joints.size();
5449 coords += average * scale;
5450 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5451 skeleton.joints[j].position -= average;
5453 average /= multiplier;
5457 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5458 velocity += skeleton.joints[i].velocity * scale;
5460 velocity /= skeleton.joints.size();
5462 if (!isnormal(velocity.x) && velocity.x) {
5466 if (findLength(&average) < 10 && dead && skeleton.free) {
5467 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5468 if (skeleton.longdead > 2000) {
5469 if (skeleton.longdead > 6000) {
5471 pause_sound(whooshsound);
5477 if (dead == 2 && bloodloss < damagetolerance) {
5479 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5481 if (bloodtoggle && !bled) {
5482 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5483 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5484 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5485 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5486 float size = .2 * 1.2;
5489 Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5494 if (dead == 2 && bloodloss >= damagetolerance) {
5496 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5497 if (bleeding <= 0) {
5500 if (bloodtoggle && !bled) {
5501 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5502 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5503 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5504 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5508 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5516 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5517 bool canrecover = 1;
5518 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5519 startpoint = coords;
5522 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1) {
5525 if (velocity.y < -30) {
5528 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5529 if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) {
5530 colviewer = startpoint;
5531 coltarget = endpoint;
5532 if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1) {
5542 terrainnormal = jointPos(groin) - jointPos(abdomen);
5543 if (joint(groin).locked && joint(abdomen).locked) {
5544 terrainnormal = jointPos(groin) - jointPos(abdomen);
5545 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5547 if (joint(abdomen).locked && joint(neck).locked) {
5548 terrainnormal = jointPos(abdomen) - jointPos(neck);
5549 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5551 if (joint(groin).locked && joint(neck).locked) {
5552 terrainnormal = jointPos(groin) - jointPos(neck);
5553 middle = (jointPos(groin) + jointPos(neck)) / 2;
5555 Normalise(&terrainnormal);
5557 targetyaw = -asin(0 - terrainnormal.x);
5558 targetyaw *= 360 / 6.28;
5559 if (terrainnormal.z < 0) {
5560 targetyaw = 180 - targetyaw;
5565 animTarget = flipanim;
5566 crouchtogglekeydown = 1;
5571 animCurrent = tempanim;
5575 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5576 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5577 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5582 if (findLength(&average) < 10 && !dead && skeleton.free) {
5583 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5584 if (skeleton.longdead > (damage + 500) * 1.5) {
5586 pause_sound(whooshsound);
5593 terrainnormal = jointPos(groin) - jointPos(abdomen);
5594 if (joint(groin).locked && joint(abdomen).locked) {
5595 terrainnormal = jointPos(groin) - jointPos(abdomen);
5596 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5598 if (joint(abdomen).locked && joint(neck).locked) {
5599 terrainnormal = jointPos(abdomen) - jointPos(neck);
5600 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5602 if (joint(groin).locked && joint(neck).locked) {
5603 terrainnormal = jointPos(groin) - jointPos(neck);
5604 middle = (jointPos(groin) + jointPos(neck)) / 2;
5606 Normalise(&terrainnormal);
5608 targetyaw = -asin(0 - terrainnormal.x);
5609 targetyaw *= 360 / 6.28;
5610 if (terrainnormal.z < 0) {
5611 targetyaw = 180 - targetyaw;
5615 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5617 if (skeleton.forward.y < 0) {
5618 animTarget = getupfrombackanim;
5622 if (skeleton.forward.y > -.3) {
5623 animTarget = getupfromfrontanim;
5631 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5632 animTarget = rollanim;
5633 targetyaw = lookyaw;
5637 if (forwardkeydown) {
5646 if (forwardkeydown) {
5654 if (!leftkeydown && !rightkeydown) {
5662 if (abs(targettilt2) > 50) {
5665 animCurrent = tempanim;
5668 tilt2 = targettilt2;
5670 if (middle.y > 0 && animTarget != rollanim) {
5671 targetoffset.y = middle.y + 1;
5674 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5675 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5676 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5683 if (num_weapons > 0) {
5684 if (weapons[0].getType() == staff) {
5688 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5689 if (velocity.y > -30) {
5691 tempvelocity = velocity;
5692 Normalise(&tempvelocity);
5693 targetyaw = -asin(0 - tempvelocity.x);
5694 targetyaw *= 360 / 6.28;
5695 if (velocity.z < 0) {
5696 targetyaw = 180 - targetyaw;
5701 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5702 animTarget = rollanim;
5705 animTarget = backhandspringanim;
5711 emit_sound_at(movewhooshsound, coords, 128.);
5713 animCurrent = animTarget;
5714 frameCurrent = frameTarget - 1;
5726 if (skeleton.freefall == 0) {
5731 if (aitype != passivetype || skeleton.free == 1) {
5732 if (findLengthfast(&velocity) > .1) {
5733 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5734 if (Object::objects[i]->type == firetype) {
5735 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) {
5737 if (!Object::objects[i]->onfire) {
5738 emit_sound_at(firestartsound, Object::objects[i]->position);
5740 Object::objects[i]->onfire = 1;
5743 if (Object::objects[i]->onfire) {
5749 if (Object::objects[i]->type == bushtype) {
5750 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) {
5752 if (!Object::objects[i]->onfire) {
5753 emit_sound_at(firestartsound, Object::objects[i]->position);
5755 Object::objects[i]->onfire = 1;
5759 if (Object::objects[i]->onfire) {
5763 if (Object::objects[i]->messedwith <= 0) {
5767 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5770 addEnvSound(coords, 4 * findLength(&velocity));
5774 if (environment == grassyenvironment) {
5775 howmany = findLength(&velocity) * 4;
5777 if (environment == snowyenvironment) {
5778 howmany = findLength(&velocity) * 2;
5781 if (environment != desertenvironment) {
5782 for (int j = 0; j < howmany; j++) {
5783 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5784 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5785 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5788 pos.x += float(abs(Random() % 100) - 50) / 200;
5789 pos.y += float(abs(Random() % 100) - 50) / 200;
5790 pos.z += float(abs(Random() % 100) - 50) / 200;
5791 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);
5792 Sprite::setLastSpriteSpecial(1);
5796 howmany = findLength(&velocity) * 4;
5798 if (environment == snowyenvironment) {
5799 for (int j = 0; j < howmany; j++) {
5800 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5801 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5802 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5805 pos.x += float(abs(Random() % 100) - 50) / 200;
5806 pos.y += float(abs(Random() % 100) - 50) / 200;
5807 pos.z += float(abs(Random() % 100) - 50) / 200;
5808 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5809 Sprite::setLastSpriteSpecial(2);
5814 Object::objects[i]->rotx += velocity.x * multiplier * 6;
5815 Object::objects[i]->roty += velocity.z * multiplier * 6;
5816 Object::objects[i]->messedwith = .5;
5820 if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) {
5821 if (Object::objects[i]->pitch == 0) {
5824 tempcoord = coords - Object::objects[i]->position;
5825 tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0);
5826 tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0);
5827 tempcoord += Object::objects[i]->position;
5829 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) {
5830 if (Object::objects[i]->messedwith <= 0) {
5834 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5837 addEnvSound(coords, 4 * findLength(&velocity));
5841 if (environment == grassyenvironment) {
5842 howmany = findLength(&velocity) * 4;
5844 if (environment == snowyenvironment) {
5845 howmany = findLength(&velocity) * 2;
5848 if (environment != desertenvironment) {
5849 for (int j = 0; j < howmany; j++) {
5850 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5851 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5852 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5854 pos += velocity * .1;
5856 pos.x += float(abs(Random() % 100) - 50) / 150;
5857 pos.y += float(abs(Random() % 100) - 50) / 150;
5858 pos.z += float(abs(Random() % 100) - 50) / 150;
5859 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);
5860 Sprite::setLastSpriteSpecial(1);
5864 howmany = findLength(&velocity) * 4;
5866 if (environment == snowyenvironment) {
5867 for (int j = 0; j < howmany; j++) {
5868 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5869 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5870 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5872 pos += velocity * .1;
5874 pos.x += float(abs(Random() % 100) - 50) / 150;
5875 pos.y += float(abs(Random() % 100) - 50) / 150;
5876 pos.z += float(abs(Random() % 100) - 50) / 150;
5877 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5878 Sprite::setLastSpriteSpecial(2);
5883 Object::objects[i]->messedwith = .5;
5890 if (!skeleton.free) {
5893 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype) {
5897 if (aitype != passivetype && victim->skeleton.free && !victim->dead) {
5901 if (Tutorial::active && id != 0) {
5904 if (play && aitype != playercontrolled) {
5905 int whichsound = -1;
5906 if (speechdelay <= 0) {
5907 unsigned int i = abs(Random() % 4);
5909 whichsound = PersonType::types[creature].soundsTalk[i];
5914 if (whichsound != -1) {
5915 emit_sound_at(whichsound, coords);
5919 if (animTarget == staggerbackhighanim) {
5922 if (animTarget == staggerbackhardanim) {
5925 staggerdelay -= multiplier;
5926 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
5929 if (velocity.y < -30 && animTarget == jumpdownanim) {
5932 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5933 animTarget = getIdle();
5937 weaponmissdelay -= multiplier;
5938 highreversaldelay -= multiplier;
5939 lowreversaldelay -= multiplier;
5940 lastcollide -= multiplier;
5941 skiddelay -= multiplier;
5942 if (!isnormal(velocity.x) && velocity.x) {
5945 if (!isnormal(targettilt) && targettilt) {
5948 if (!isnormal(targettilt2) && targettilt2) {
5951 if (!isnormal(targetyaw) && targetyaw) {
5955 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5956 //open hands and close mouth
5957 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5958 righthandmorphness = 0;
5959 righthandmorphend = 0;
5960 targetrighthandmorphness = 1;
5963 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5964 lefthandmorphness = 0;
5965 lefthandmorphend = 0;
5966 targetlefthandmorphness = 1;
5969 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5972 targetheadmorphness = 1;
5976 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) {
5977 //open hands and mouth
5978 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5979 righthandmorphness = 0;
5980 righthandmorphend = 0;
5981 targetrighthandmorphness = 1;
5984 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5985 lefthandmorphness = 0;
5986 lefthandmorphend = 0;
5987 targetlefthandmorphness = 1;
5990 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5993 targetheadmorphness = 1;
5997 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5998 //close hands and mouth
5999 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
6000 righthandmorphness = 0;
6001 righthandmorphend = 1;
6002 targetrighthandmorphness = 1;
6005 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
6006 lefthandmorphness = 0;
6007 lefthandmorphend = 1;
6008 targetlefthandmorphness = 1;
6011 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
6014 targetheadmorphness = 1;
6018 if (animTarget == spinkickanim ||
6019 animTarget == staffspinhitreversalanim ||
6020 animTarget == staffspinhitreversedanim ||
6021 animTarget == staffhitreversalanim ||
6022 animTarget == staffhitreversedanim ||
6023 animTarget == hurtidleanim ||
6024 animTarget == winduppunchanim ||
6025 animTarget == swordslashreversalanim ||
6026 animTarget == swordslashreversedanim ||
6027 animTarget == knifeslashreversalanim ||
6028 animTarget == knifeslashreversedanim ||
6029 animTarget == knifethrowanim ||
6030 animTarget == knifefollowanim ||
6031 animTarget == knifefollowedanim ||
6032 animTarget == killanim ||
6033 animTarget == dropkickanim ||
6034 animTarget == upunchanim ||
6035 animTarget == knifeslashstartanim ||
6036 animTarget == swordslashanim ||
6037 animTarget == staffhitanim ||
6038 animTarget == staffspinhitanim ||
6039 animTarget == staffgroundsmashanim ||
6040 animTarget == spinkickreversalanim ||
6041 animTarget == sweepreversalanim ||
6042 animTarget == lowkickanim ||
6043 animTarget == sweepreversedanim ||
6044 animTarget == rabbitkickreversalanim ||
6045 animTarget == rabbitkickreversedanim ||
6046 animTarget == jumpreversalanim ||
6047 animTarget == jumpreversedanim) {
6048 //close hands and yell
6049 if (righthandmorphend != 1 &&
6050 righthandmorphness == targetrighthandmorphness) {
6051 righthandmorphness = 0;
6052 righthandmorphend = 1;
6053 targetrighthandmorphness = 1;
6056 if (lefthandmorphend != 1 &&
6057 lefthandmorphness == targetlefthandmorphness) {
6058 lefthandmorphness = 0;
6059 lefthandmorphend = 1;
6060 targetlefthandmorphness = 1;
6063 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
6066 targetheadmorphness = 1;
6073 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
6074 (victim->aitype != searchtype) && (aitype != passivetype) &&
6075 (aitype != searchtype) && (victim->id < Person::players.size())) {
6076 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
6080 if (!dead && animTarget != hurtidleanim) {
6081 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
6082 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
6085 targetheadmorphness = 1;
6090 if (weaponactive != -1) {
6091 if (weapons[weaponids[weaponactive]].getType() != staff) {
6092 righthandmorphstart = 1;
6093 righthandmorphend = 1;
6095 if (weapons[weaponids[weaponactive]].getType() == staff) {
6096 righthandmorphstart = 2;
6097 righthandmorphend = 2;
6099 targetrighthandmorphness = 1;
6102 terrainnormal = terrain.getNormal(coords.x, coords.z);
6104 if (Animation::animations[animTarget].attack != reversal) {
6105 if (!isnormal(coords.x)) {
6114 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
6115 facing = flatfacing;
6116 ReflectVector(&facing, terrainnormal);
6120 animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
6122 targettilt2 = -facing.y * 20;
6128 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim) {
6131 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6132 flatvelocity = velocity;
6134 flatvelspeed = findLength(&flatvelocity);
6135 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
6136 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
6137 if (velocity.y < 0) {
6140 if (velocity.y < 0) {
6143 if (targettilt > 25) {
6146 if (targettilt < -25) {
6151 if (targettilt2 > 45) {
6154 if (targettilt2 < -45) {
6157 if (abs(tilt2 - targettilt2) < multiplier * 400) {
6158 tilt2 = targettilt2;
6159 } else if (tilt2 > targettilt2) {
6160 tilt2 -= multiplier * 400;
6161 } else if (tilt2 < targettilt2) {
6162 tilt2 += multiplier * 400;
6164 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
6173 if (!isnormal(targettilt) && targettilt) {
6176 if (!isnormal(targettilt2) && targettilt2) {
6181 if (animTarget == rabbittackleanim) {
6182 velocity += facing * multiplier * speed * 700 * scale;
6183 velspeed = findLength(&velocity);
6184 if (velspeed > speed * 65 * scale) {
6185 velocity /= velspeed;
6186 velspeed = speed * 65 * scale;
6187 velocity *= velspeed;
6189 velocity.y += gravity * multiplier * 20;
6190 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6191 velspeed = findLength(&velocity);
6192 velocity = flatfacing * velspeed;
6194 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
6195 if (isRun() || animTarget == rabbitkickanim) {
6196 velocity += facing * multiplier * speed * 700 * scale;
6197 velspeed = findLength(&velocity);
6198 if (velspeed > speed * 45 * scale) {
6199 velocity /= velspeed;
6200 velspeed = speed * 45 * scale;
6201 velocity *= velspeed;
6203 velocity.y += gravity * multiplier * 20;
6204 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6205 velspeed = findLength(&velocity);
6206 if (velspeed < speed * 30 * scale) {
6207 velspeed = speed * 30 * scale;
6209 velocity = flatfacing * velspeed;
6211 } else if (isRun()) {
6212 velocity += facing * multiplier * speed * 700 * scale;
6213 velspeed = findLength(&velocity);
6214 if (creature == rabbittype) {
6215 if (velspeed > speed * 55 * scale) {
6216 velocity /= velspeed;
6217 velspeed = speed * 55 * scale;
6218 velocity *= velspeed;
6221 if (creature == wolftype) {
6222 if (velspeed > speed * 75 * scale) {
6223 velocity /= velspeed;
6224 velspeed = speed * 75 * scale;
6225 velocity *= velspeed;
6228 velocity.y += gravity * multiplier * 20;
6229 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6230 velspeed = findLength(&velocity);
6231 velocity = flatfacing * velspeed;
6234 if (animTarget == rollanim && targetFrame().label != 6) {
6235 velocity += facing * multiplier * speed * 700 * scale;
6236 velspeed = findLength(&velocity);
6237 if (velspeed > speed * 45 * scale) {
6238 velocity /= velspeed;
6239 velspeed = speed * 45 * scale;
6240 velocity *= velspeed;
6242 velocity.y += gravity * multiplier * 20;
6243 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6244 velspeed = findLength(&velocity);
6245 velocity = flatfacing * velspeed;
6248 if (animTarget == sneakanim || animTarget == walkanim) {
6249 velocity += facing * multiplier * speed * 700 * scale;
6250 velspeed = findLength(&velocity);
6251 if (velspeed > speed * 12 * scale) {
6252 velocity /= velspeed;
6253 velspeed = speed * 12 * scale;
6254 velocity *= velspeed;
6256 velocity.y += gravity * multiplier * 20;
6257 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6258 velspeed = findLength(&velocity);
6259 velocity = flatfacing * velspeed;
6262 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
6263 velocity += facing * multiplier * speed * 700 * scale;
6264 velspeed = findLength(&velocity);
6265 if (velspeed > speed * 2 * scale) {
6266 velocity /= velspeed;
6267 velspeed = speed * 2 * scale;
6268 velocity *= velspeed;
6270 velocity.y += gravity * multiplier * 20;
6271 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6272 velspeed = findLength(&velocity);
6273 velocity = flatfacing * velspeed;
6276 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
6277 velocity -= facing * multiplier * speed * 700 * scale;
6278 velspeed = findLength(&velocity);
6279 if (velspeed > speed * 2 * scale) {
6280 velocity /= velspeed;
6281 velspeed = speed * 2 * scale;
6282 velocity *= velspeed;
6284 velocity.y += gravity * multiplier * 20;
6285 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6286 velspeed = findLength(&velocity);
6287 velocity = flatfacing * velspeed * -1;
6290 if (animTarget == fightsidestep) {
6291 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
6292 velspeed = findLength(&velocity);
6293 if (velspeed > speed * 12 * scale) {
6294 velocity /= velspeed;
6295 velspeed = speed * 12 * scale;
6296 velocity *= velspeed;
6298 velocity.y += gravity * multiplier * 20;
6299 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6300 velspeed = findLength(&velocity);
6301 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
6304 if (animTarget == staggerbackhighanim) {
6305 coords -= facing * multiplier * speed * 16 * scale;
6308 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
6309 coords -= facing * multiplier * speed * 20 * scale;
6313 if (animTarget == backhandspringanim) {
6314 //coords-=facing*multiplier*50*scale;
6315 velocity += facing * multiplier * speed * 700 * scale * -1;
6316 velspeed = findLength(&velocity);
6317 if (velspeed > speed * 50 * scale) {
6318 velocity /= velspeed;
6319 velspeed = speed * 50 * scale;
6320 velocity *= velspeed;
6322 velocity.y += gravity * multiplier * 20;
6323 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6324 velspeed = findLength(&velocity);
6325 velocity = flatfacing * velspeed * -1;
6327 if (animTarget == dodgebackanim) {
6328 //coords-=facing*multiplier*50*scale;
6329 velocity += facing * multiplier * speed * 700 * scale * -1;
6330 velspeed = findLength(&velocity);
6331 if (velspeed > speed * 60 * scale) {
6332 velocity /= velspeed;
6333 velspeed = speed * 60 * scale;
6334 velocity *= velspeed;
6336 velocity.y += gravity * multiplier * 20;
6337 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6338 velspeed = findLength(&velocity);
6339 velocity = flatfacing * velspeed * -1;
6342 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6343 velspeed = findLength(&velocity);
6346 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6347 velocity.y += gravity * multiplier;
6350 if (animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6351 coords += velocity * multiplier;
6354 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6355 if (isFlip() && targetFrame().label == 7) {
6359 if (animTarget == jumpupanim) {
6361 animTarget = getIdle();
6368 pause_sound(whooshsound);
6369 OPENAL_SetVolume(channels[whooshsound], 0);
6372 if (animTarget == jumpdownanim || isFlip()) {
6376 animTarget = getLanding();
6377 emit_sound_at(landsound, coords, 128.);
6380 addEnvSound(coords);
6385 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6386 coords.y += gravity * multiplier * 2;
6388 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
6389 coords.y = terrain.getHeight(coords.x, coords.z);
6393 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)) {
6394 velspeed = findLength(&velocity);
6396 if (velspeed < multiplier * 300 * scale) {
6399 velocity -= velocity / velspeed * multiplier * 300 * scale;
6401 if (velspeed > 5 && (isLanding() || isLandhard())) {
6402 skiddingdelay += multiplier;
6403 if (skiddelay <= 0) {
6404 FootLand(leftfoot, .5);
6405 FootLand(rightfoot, .5);
6414 velspeed = findLength(&velocity);
6416 if (velspeed > 5 && (isLanding() || isLandhard())) {
6417 skiddingdelay += multiplier;
6418 if (skiddelay <= 0) {
6419 FootLand(leftfoot, .5);
6420 FootLand(rightfoot, .5);
6428 if (skiddingdelay < 0) {
6429 skiddingdelay += multiplier;
6431 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
6433 if (!onterrain || environment == grassyenvironment) {
6434 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
6436 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
6440 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
6441 terrainnormal = victim->coords - coords;
6442 Normalise(&terrainnormal);
6443 targetyaw = -asin(0 - terrainnormal.x);
6444 targetyaw *= 360 / 6.28;
6445 if (terrainnormal.z < 0) {
6446 targetyaw = 180 - targetyaw;
6448 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
6451 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
6452 targetyaw = victim->targetyaw;
6454 if (animTarget == rabbittacklinganim) {
6455 coords = victim->coords;
6458 skeleton.oldfree = skeleton.free;
6462 midterrain.x = terrain.size * terrain.scale / 2;
6463 midterrain.z = terrain.size * terrain.scale / 2;
6464 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
6466 tempposit = coords - midterrain;
6468 Normalise(&tempposit);
6469 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
6470 coords.x = tempposit.x + midterrain.x;
6471 coords.z = tempposit.z + midterrain.z;
6476 * inverse kinematics helper function
6478 void IKHelper(Person* p, float interp)
6480 XYZ point, change, change2;
6481 float heightleft, heightright;
6483 // TODO: implement localToWorld and worldToLocal
6484 // but keep in mind it won't be the same math if player is ragdolled or something
6485 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
6486 // then comb through code for places where to use it
6488 // point = localToWorld(jointPos(leftfoot))
6489 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
6490 // adjust height of foot
6491 heightleft = terrain.getHeight(point.x, point.z) + .04;
6492 point.y = heightleft;
6493 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
6494 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
6495 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
6496 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
6497 // move ankle along with foot
6498 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
6499 // average knee pos between old and new pos
6500 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
6502 // do same as above for right leg
6503 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
6504 heightright = terrain.getHeight(point.x, point.z) + .04;
6505 point.y = heightright;
6506 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
6507 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
6508 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
6509 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
6510 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
6512 // fix up skeleton now that we've moved body parts?
6513 p->skeleton.DoConstraints(&p->coords, &p->scale);
6520 int Person::DrawSkeleton()
6522 int oldplayerdetail;
6523 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6524 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6534 glAlphaFunc(GL_GREATER, 0.0001);
6536 float terrainheight;
6538 if (!isnormal(yaw)) {
6541 if (!isnormal(tilt)) {
6544 if (!isnormal(tilt2)) {
6547 oldplayerdetail = playerdetail;
6549 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6552 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6555 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6561 if (playerdetail != oldplayerdetail) {
6563 normalsupdatedelay = 0;
6565 static float updatedelaychange;
6566 static float morphness;
6567 static float framemult;
6569 skeleton.FindForwards();
6570 if (howactive == typesittingwall) {
6571 skeleton.specialforward[1] = 0;
6572 skeleton.specialforward[1].z = 1;
6578 static int weaponattachmuscle;
6579 static int weaponrotatemuscle;
6580 static XYZ weaponpoint;
6581 static int start, endthing;
6582 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6583 if (!isSleeping() && !isSitting()) {
6584 // TODO: give these meaningful names
6585 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6586 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard() || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6588 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6590 if (creature == wolftype) {
6595 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6596 IKHelper(this, target);
6597 if (creature == wolftype) {
6598 IKHelper(this, target);
6602 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6603 IKHelper(this, 1 - target);
6604 if (creature == wolftype) {
6605 IKHelper(this, 1 - target);
6610 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())) {
6613 targetheadyaw = -targetyaw;
6614 targetheadpitch = 0;
6615 if (Animation::animations[animTarget].attack == 3) {
6616 targetheadyaw += 180;
6619 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6620 skeleton.drawmodel.vertex[i] = 0;
6621 skeleton.drawmodel.vertex[i].y = 999;
6623 for (int i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6624 skeleton.drawmodellow.vertex[i] = 0;
6625 skeleton.drawmodellow.vertex[i].y = 999;
6627 for (int i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6628 skeleton.drawmodelclothes.vertex[i] = 0;
6629 skeleton.drawmodelclothes.vertex[i].y = 999;
6631 for (unsigned int i = 0; i < skeleton.muscles.size(); i++) {
6632 // convenience renames
6633 const int p1 = skeleton.muscles[i].parent1->label;
6634 const int p2 = skeleton.muscles[i].parent2->label;
6636 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6641 if (p1 == righthand || p2 == righthand) {
6642 morphness = righthandmorphness;
6643 start = righthandmorphstart;
6644 endthing = righthandmorphend;
6646 if (p1 == lefthand || p2 == lefthand) {
6647 morphness = lefthandmorphness;
6648 start = lefthandmorphstart;
6649 endthing = lefthandmorphend;
6651 if (p1 == head || p2 == head) {
6652 morphness = headmorphness;
6653 start = headmorphstart;
6654 endthing = headmorphend;
6656 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6657 morphness = chestmorphness;
6658 start = chestmorphstart;
6659 endthing = chestmorphend;
6661 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6662 morphness = tailmorphness;
6663 start = tailmorphstart;
6664 endthing = tailmorphend;
6667 skeleton.FindRotationMuscle(i, animTarget);
6669 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6670 glMatrixMode(GL_MODELVIEW);
6673 if (!skeleton.free) {
6674 glRotatef(tilt2, 1, 0, 0);
6676 if (!skeleton.free) {
6677 glRotatef(tilt, 0, 0, 1);
6680 glTranslatef(mid.x, mid.y, mid.z);
6682 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6683 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6685 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6686 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6688 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6689 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6691 if (playerdetail || skeleton.free == 3) {
6692 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6693 XYZ& v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6694 XYZ& v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6695 glMatrixMode(GL_MODELVIEW);
6697 if (p1 == abdomen || p2 == abdomen) {
6698 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(1).x,
6699 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(1).y,
6700 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(1).z);
6702 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6703 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(2).x,
6704 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(2).y,
6705 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(2).z);
6707 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6708 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(3).x,
6709 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(3).y,
6710 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(3).z);
6712 if (p1 == head || p2 == head) {
6713 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(0).x,
6714 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(0).y,
6715 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(0).z);
6717 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6718 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6719 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6720 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6724 if (!playerdetail || skeleton.free == 3) {
6725 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6726 XYZ& v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6727 glMatrixMode(GL_MODELVIEW);
6729 if (p1 == abdomen || p2 == abdomen) {
6730 glTranslatef(v0.x * getProportion(1).x,
6731 v0.y * getProportion(1).y,
6732 v0.z * getProportion(1).z);
6734 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6735 glTranslatef(v0.x * getProportion(2).x,
6736 v0.y * getProportion(2).y,
6737 v0.z * getProportion(2).z);
6739 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6740 glTranslatef(v0.x * getProportion(3).x,
6741 v0.y * getProportion(3).y,
6742 v0.z * getProportion(3).z);
6744 if (p1 == head || p2 == head) {
6745 glTranslatef(v0.x * getProportion(0).x,
6746 v0.y * getProportion(0).y,
6747 v0.z * getProportion(0).z);
6750 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6751 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6752 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6753 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6759 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6760 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6762 glMatrixMode(GL_MODELVIEW);
6765 if (!skeleton.free) {
6766 glRotatef(tilt2, 1, 0, 0);
6768 if (!skeleton.free) {
6769 glRotatef(tilt, 0, 0, 1);
6771 glTranslatef(mid.x, mid.y, mid.z);
6772 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6773 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6775 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6776 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6778 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6779 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6781 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6782 XYZ& v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6783 glMatrixMode(GL_MODELVIEW);
6785 if (p1 == abdomen || p2 == abdomen) {
6786 glTranslatef(v0.x * getProportion(1).x,
6787 v0.y * getProportion(1).y,
6788 v0.z * getProportion(1).z);
6790 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6791 glTranslatef(v0.x * getProportion(2).x,
6792 v0.y * getProportion(2).y,
6793 v0.z * getProportion(2).z);
6795 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6796 glTranslatef(v0.x * getProportion(3).x,
6797 v0.y * getProportion(3).y,
6798 v0.z * getProportion(3).z);
6800 if (p1 == head || p2 == head) {
6801 glTranslatef(v0.x * getProportion(0).x,
6802 v0.y * getProportion(0).y,
6803 v0.z * getProportion(0).z);
6805 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6806 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6807 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6808 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6813 updatedelay = 1 + (float)(Random() % 100) / 1000;
6815 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6816 normalsupdatedelay = 1;
6817 if (playerdetail || skeleton.free == 3) {
6818 skeleton.drawmodel.CalculateNormals(0);
6820 if (!playerdetail || skeleton.free == 3) {
6821 skeleton.drawmodellow.CalculateNormals(0);
6823 if (skeleton.clothes) {
6824 skeleton.drawmodelclothes.CalculateNormals(0);
6827 if (playerdetail || skeleton.free == 3) {
6828 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6830 if (!playerdetail || skeleton.free == 3) {
6831 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6833 if (skeleton.clothes) {
6834 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6839 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6840 if (updatedelaychange > -realmultiplier * 30) {
6841 updatedelaychange = -realmultiplier * 30;
6843 if (updatedelaychange > -framemult * 4) {
6844 updatedelaychange = -framemult * 4;
6846 if (skeleton.free == 1) {
6847 updatedelaychange *= 6;
6850 updatedelaychange *= 8;
6852 updatedelay += updatedelaychange;
6854 glMatrixMode(GL_MODELVIEW);
6856 glTranslatef(coords.x, coords.y - .02, coords.z);
6857 if (!skeleton.free) {
6858 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6859 glRotatef(yaw, 0, 1, 0);
6863 glColor4f(.4, 1, .4, 1);
6864 glDisable(GL_LIGHTING);
6865 glDisable(GL_TEXTURE_2D);
6868 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6869 XYZ& v0 = skeleton.drawmodel.vertex[i];
6870 glVertex3f(v0.x, v0.y, v0.z);
6877 for (unsigned int i = 0; i < skeleton.drawmodel.Triangles.size(); i++) {
6878 const XYZ& v0 = skeleton.drawmodel.getTriangleVertex(i, 0);
6879 const XYZ& v1 = skeleton.drawmodel.getTriangleVertex(i, 1);
6880 const XYZ& v2 = skeleton.drawmodel.getTriangleVertex(i, 2);
6881 glVertex3f(v0.x, v0.y, v0.z);
6882 glVertex3f(v1.x, v1.y, v1.z);
6883 glVertex3f(v1.x, v1.y, v1.z);
6884 glVertex3f(v2.x, v2.y, v2.z);
6885 glVertex3f(v2.x, v2.y, v2.z);
6886 glVertex3f(v0.x, v0.y, v0.z);
6893 terrainlight = terrain.getLighting(coords.x, coords.z);
6894 distance = distsq(&viewer, &coords);
6895 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6900 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6901 if (terrainheight < 1) {
6904 if (terrainheight > 1.7) {
6905 terrainheight = 1.7;
6908 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6909 glDisable(GL_BLEND);
6910 glAlphaFunc(GL_GREATER, 0.0001);
6911 glEnable(GL_TEXTURE_2D);
6913 glDisable(GL_TEXTURE_2D);
6914 glColor4f(.7, .35, 0, .5);
6916 glEnable(GL_LIGHTING);
6919 if (Tutorial::active && id != 0) {
6920 glColor4f(.7, .7, .7, 0.6);
6922 glEnable(GL_LIGHTING);
6924 if (canattack && cananger) {
6925 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6926 glDisable(GL_TEXTURE_2D);
6927 glColor4f(1, 0, 0, 0.8);
6930 glMatrixMode(GL_TEXTURE);
6932 glTranslatef(0, -smoketex, 0);
6933 glTranslatef(-smoketex, 0, 0);
6937 if (Tutorial::active && (id != 0)) {
6938 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6940 skeleton.drawmodel.draw();
6944 if (!playerdetail) {
6945 if (Tutorial::active && (id != 0)) {
6946 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6948 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6952 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed)) {
6953 if (Tutorial::active && id != 0) {
6955 glMatrixMode(GL_MODELVIEW);
6956 glEnable(GL_TEXTURE_2D);
6957 glColor4f(.7, .7, .7, 0.6);
6959 glEnable(GL_LIGHTING);
6961 if (canattack && cananger) {
6962 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6963 glDisable(GL_TEXTURE_2D);
6964 glColor4f(1, 0, 0, 0.8);
6967 glMatrixMode(GL_TEXTURE);
6969 glTranslatef(0, -smoketex * .6, 0);
6970 glTranslatef(smoketex * .6, 0, 0);
6973 if (Tutorial::active && (id != 0)) {
6974 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6976 skeleton.drawmodel.draw();
6980 if (!playerdetail) {
6981 if (Tutorial::active && (id != 0)) {
6982 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6984 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6990 if (Tutorial::active && id != 0) {
6992 glMatrixMode(GL_MODELVIEW);
6993 glEnable(GL_TEXTURE_2D);
6995 if (skeleton.clothes) {
6999 skeleton.drawmodelclothes.draw();
7002 skeleton.drawmodelclothes.drawimmediate();
7009 if (num_weapons > 0) {
7010 for (k = 0; k < num_weapons; k++) {
7011 int i = weaponids[k];
7012 if (weaponactive == k) {
7013 if (weapons[i].getType() != staff) {
7014 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7015 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
7016 weaponattachmuscle = j;
7019 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7020 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) {
7021 weaponrotatemuscle = j;
7024 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
7025 if (creature == wolftype) {
7026 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
7029 if (weapons[i].getType() == staff) {
7030 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7031 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
7032 weaponattachmuscle = j;
7035 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7036 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) {
7037 weaponrotatemuscle = j;
7040 //weaponpoint=jointPos(rightwrist);
7041 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
7042 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
7043 XYZ tempnormthing, vec1, vec2;
7044 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
7045 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
7046 CrossProduct(&vec1, &vec2, &tempnormthing);
7047 Normalise(&tempnormthing);
7048 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim) {
7049 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
7053 if (weaponactive != k && weaponstuck != k) {
7054 if (weapons[i].getType() == knife) {
7055 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
7057 if (weapons[i].getType() == sword) {
7058 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
7060 if (weapons[i].getType() == staff) {
7061 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
7063 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7064 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) {
7065 weaponrotatemuscle = j;
7069 if (weaponstuck == k) {
7070 if (weaponstuckwhere == 0) {
7071 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
7073 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
7075 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7076 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) {
7077 weaponrotatemuscle = j;
7081 if (skeleton.free) {
7082 weapons[i].position = weaponpoint * scale + coords;
7083 weapons[i].bigrotation = 0;
7084 weapons[i].bigtilt = 0;
7085 weapons[i].bigtilt2 = 0;
7087 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;
7088 weapons[i].bigrotation = yaw;
7089 weapons[i].bigtilt = tilt;
7090 weapons[i].bigtilt2 = tilt2;
7092 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
7093 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
7094 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
7095 if (weaponactive == k) {
7096 if (weapons[i].getType() == knife) {
7097 weapons[i].smallrotation = 180;
7098 weapons[i].smallrotation2 = 0;
7099 if (isCrouch() || wasCrouch()) {
7100 weapons[i].smallrotation2 = 20;
7102 if (animTarget == hurtidleanim) {
7103 weapons[i].smallrotation2 = 50;
7105 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
7106 XYZ temppoint1, temppoint2;
7109 temppoint1 = jointPos(righthand);
7110 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7111 distance = findDistance(&temppoint1, &temppoint2);
7112 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7113 weapons[i].rotation2 *= 360 / 6.28;
7116 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7117 weapons[i].rotation1 *= 360 / 6.28;
7118 weapons[i].rotation3 = 0;
7119 weapons[i].smallrotation = -90;
7120 weapons[i].smallrotation2 = 0;
7121 if (temppoint1.x > temppoint2.x) {
7122 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7125 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
7126 XYZ temppoint1, temppoint2;
7129 temppoint1 = jointPos(righthand);
7130 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7131 distance = findDistance(&temppoint1, &temppoint2);
7132 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7133 weapons[i].rotation2 *= 360 / 6.28;
7136 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7137 weapons[i].rotation1 *= 360 / 6.28;
7138 weapons[i].rotation3 = 0;
7139 weapons[i].smallrotation = 90;
7140 weapons[i].smallrotation2 = 0;
7141 if (temppoint1.x > temppoint2.x) {
7142 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7145 if (animTarget == knifethrowanim) {
7146 weapons[i].smallrotation = 90;
7147 //weapons[i].smallrotation2=-90;
7148 weapons[i].smallrotation2 = 0;
7149 weapons[i].rotation1 = 0;
7150 weapons[i].rotation2 = 0;
7151 weapons[i].rotation3 = 0;
7153 if (animTarget == knifesneakattackanim && frameTarget < 5) {
7154 weapons[i].smallrotation = -90;
7155 weapons[i].rotation1 = 0;
7156 weapons[i].rotation2 = 0;
7157 weapons[i].rotation3 = 0;
7160 if (weapons[i].getType() == sword) {
7161 weapons[i].smallrotation = 0;
7162 weapons[i].smallrotation2 = 0;
7163 if (animTarget == knifethrowanim) {
7164 weapons[i].smallrotation = -90;
7165 weapons[i].smallrotation2 = 0;
7166 weapons[i].rotation1 = 0;
7167 weapons[i].rotation2 = 0;
7168 weapons[i].rotation3 = 0;
7170 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)) {
7171 XYZ temppoint1, temppoint2;
7174 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
7175 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7176 distance = findDistance(&temppoint1, &temppoint2);
7177 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7178 weapons[i].rotation2 *= 360 / 6.28;
7181 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7182 weapons[i].rotation1 *= 360 / 6.28;
7183 weapons[i].rotation3 = 0;
7184 weapons[i].smallrotation = 90;
7185 weapons[i].smallrotation2 = 0;
7186 if (temppoint1.x > temppoint2.x) {
7187 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7191 if (weapons[i].getType() == staff) {
7192 weapons[i].smallrotation = 100;
7193 weapons[i].smallrotation2 = 0;
7194 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
7195 XYZ temppoint1, temppoint2;
7198 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
7199 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7200 distance = findDistance(&temppoint1, &temppoint2);
7201 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7202 weapons[i].rotation2 *= 360 / 6.28;
7205 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7206 weapons[i].rotation1 *= 360 / 6.28;
7207 weapons[i].rotation3 = 0;
7208 weapons[i].smallrotation = 90;
7209 weapons[i].smallrotation2 = 0;
7210 if (temppoint1.x > temppoint2.x) {
7211 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7216 if (weaponactive != k && weaponstuck != k) {
7217 if (weapons[i].getType() == knife) {
7218 weapons[i].smallrotation = -70;
7219 weapons[i].smallrotation2 = 10;
7221 if (weapons[i].getType() == sword) {
7222 weapons[i].smallrotation = -100;
7223 weapons[i].smallrotation2 = -8;
7225 if (weapons[i].getType() == staff) {
7226 weapons[i].smallrotation = -100;
7227 weapons[i].smallrotation2 = -8;
7230 if (weaponstuck == k) {
7231 if (weaponstuckwhere == 0) {
7232 weapons[i].smallrotation = 180;
7234 weapons[i].smallrotation = 0;
7236 weapons[i].smallrotation2 = 10;
7243 if (skeleton.free) {
7246 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump()) {
7249 if (animCurrent != animTarget) {
7252 if (skeleton.free == 2) {
7261 int Person::SphereCheck(XYZ* p1, float radius, XYZ* p, XYZ* move, float* rotate, Model* model)
7263 static float distance;
7264 static float olddistance;
7265 static int intersecting;
7266 static int firstintersecting;
7269 static XYZ start, end;
7270 static float slopethreshold = -.4;
7272 firstintersecting = -1;
7276 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius) {
7280 *p1 = DoRotation(*p1, 0, -*rotate, 0);
7282 for (int i = 0; i < 4; i++) {
7283 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7284 if (model->Triangles[j].facenormal.y <= slopethreshold) {
7286 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)));
7287 if (distance < radius) {
7288 point = *p1 - model->Triangles[j].facenormal * distance;
7289 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]])) {
7292 if (!intersecting) {
7293 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7294 &model->vertex[model->Triangles[j].vertex[1]],
7297 if (!intersecting) {
7298 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
7299 &model->vertex[model->Triangles[j].vertex[2]],
7302 if (!intersecting) {
7303 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7304 &model->vertex[model->Triangles[j].vertex[2]],
7308 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7312 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)) {
7313 p1->y = point.y + radius;
7314 if ((animTarget == jumpdownanim || isFlip())) {
7315 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4)) {
7319 if (animTarget == jumpupanim) {
7321 animTarget = getIdle();
7328 pause_sound(whooshsound);
7329 OPENAL_SetVolume(channels[whooshsound], 0);
7332 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
7336 animTarget = getLanding();
7337 emit_sound_at(landsound, coords, 128.);
7340 addEnvSound(coords);
7347 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7348 olddistance = distance;
7349 firstintersecting = j;
7354 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7355 if (model->Triangles[j].facenormal.y > slopethreshold) {
7358 start.y -= radius / 4;
7359 XYZ& v0 = model->vertex[model->Triangles[j].vertex[0]];
7360 XYZ& v1 = model->vertex[model->Triangles[j].vertex[1]];
7361 XYZ& v2 = model->vertex[model->Triangles[j].vertex[2]];
7362 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)));
7363 if (distance < radius * .5) {
7364 point = start - model->Triangles[j].facenormal * distance;
7365 if (PointInTriangle(&point, model->Triangles[j].facenormal, &v0, &v1, &v2)) {
7368 if (!intersecting) {
7369 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
7371 if (!intersecting) {
7372 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7374 if (!intersecting) {
7375 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7378 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7379 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
7381 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;
7382 if (findLengthfast(&start) < findLengthfast(&velocity)) {
7386 *p1 += model->Triangles[j].facenormal * (distance - radius * .5);
7389 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7390 olddistance = distance;
7391 firstintersecting = j;
7398 *p = DoRotation(*p, 0, *rotate, 0);
7402 *p1 = DoRotation(*p1, 0, *rotate, 0);
7405 return firstintersecting;
7408 int findPathDist(int start, int end)
7413 unsigned int smallestcount = 1000;
7414 for (char i = 0; i < 50; i++) {
7415 unsigned int count = 0;
7420 while (last != end && count < 30) {
7422 for (int j = 0; j < Game::numpathpoints; j++) {
7423 if (j != last && j != last2 && j != last3 && j != last4) {
7425 if (Game::numpathpointconnect[j]) {
7426 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7427 if (Game::pathpointconnect[j][k] == last) {
7433 if (Game::numpathpointconnect[last]) {
7434 for (int k = 0; k < Game::numpathpointconnect[last]; k++) {
7435 if (Game::pathpointconnect[last][k] == j) {
7442 if (closest == -1 || Random() % 2 == 0) {
7454 if (count < smallestcount) {
7455 smallestcount = count;
7458 return smallestcount;
7461 void Person::takeWeapon(int weaponId)
7464 weapons[weaponId].owner = id;
7465 if (num_weapons > 0) {
7466 weaponids[num_weapons] = weaponids[0];
7469 weaponids[0] = weaponId;
7472 void Person::addClothes()
7474 if (numclothes > 0) {
7475 for (int i = 0; i < numclothes; i++) {
7482 bool Person::addClothes(const int& clothesId)
7485 const std::string fileName = clothes[clothesId];
7487 GLubyte* array = &skeleton.skinText[0];
7491 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
7496 float tintr = clothestintr[clothesId];
7497 float tintg = clothestintg[clothesId];
7498 float tintb = clothestintb[clothesId];
7520 int bytesPerPixel = texture.bpp / 8;
7524 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
7525 if (bytesPerPixel == 3) {
7527 } else if ((i + 1) % 4 == 0) {
7528 alphanum = texture.data[i];
7530 if ((i + 1) % 4 || bytesPerPixel == 3) {
7532 texture.data[i] *= tintr;
7535 texture.data[i] *= tintg;
7538 texture.data[i] *= tintb;
7540 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
7552 if (aitype != playercontrolled && !Dialog::inDialog()) {
7554 //disable movement in editor
7555 if (Game::editorenabled) {
7560 if (distsqflat(&Person::players[0]->coords, &coords) < 30 &&
7561 Person::players[0]->coords.y > coords.y + 2 &&
7562 !Person::players[0]->onterrain) {
7567 if (aitype == pathfindtype) {
7568 if (finalpathfindpoint == -1) {
7569 float closestdistance;
7570 float tempdist = 0.0f;
7574 closestdistance = -1;
7575 for (int j = 0; j < Game::numpathpoints; j++) {
7576 if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) {
7577 closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]);
7579 finaltarget = Game::pathpoint[j];
7582 finalpathfindpoint = closest;
7583 for (int j = 0; j < Game::numpathpoints; j++) {
7584 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7585 DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7586 if (sq(tempdist) < closestdistance) {
7587 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7588 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7589 closestdistance = sq(tempdist);
7591 finaltarget = colpoint;
7596 finalpathfindpoint = closest;
7598 if (targetpathfindpoint == -1) {
7599 float closestdistance;
7600 float tempdist = 0.0f;
7604 closestdistance = -1;
7605 if (lastpathfindpoint == -1) {
7606 for (int j = 0; j < Game::numpathpoints; j++) {
7607 if (j != lastpathfindpoint) {
7608 if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) {
7609 closestdistance = distsq(&coords, &Game::pathpoint[j]);
7614 targetpathfindpoint = closest;
7615 for (int j = 0; j < Game::numpathpoints; j++) {
7616 if (j != lastpathfindpoint) {
7617 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7618 DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7619 if (sq(tempdist) < closestdistance) {
7620 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7621 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7622 closestdistance = sq(tempdist);
7629 targetpathfindpoint = closest;
7631 for (int j = 0; j < Game::numpathpoints; j++) {
7632 if (j != lastpathfindpoint &&
7633 j != lastpathfindpoint2 &&
7634 j != lastpathfindpoint3 &&
7635 j != lastpathfindpoint4) {
7637 if (Game::numpathpointconnect[j]) {
7638 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7639 if (Game::pathpointconnect[j][k] == lastpathfindpoint) {
7645 if (Game::numpathpointconnect[lastpathfindpoint]) {
7646 for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++) {
7647 if (Game::pathpointconnect[lastpathfindpoint][k] == j) {
7654 tempdist = findPathDist(j, finalpathfindpoint);
7655 if (closest == -1 || tempdist < closestdistance) {
7656 closestdistance = tempdist;
7662 targetpathfindpoint = closest;
7665 losupdatedelay -= multiplier;
7667 targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]);
7668 lookyaw = targetyaw;
7670 //reached target point
7671 if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) {
7672 lastpathfindpoint4 = lastpathfindpoint3;
7673 lastpathfindpoint3 = lastpathfindpoint2;
7674 lastpathfindpoint2 = lastpathfindpoint;
7675 lastpathfindpoint = targetpathfindpoint;
7676 if (lastpathfindpoint2 == -1) {
7677 lastpathfindpoint2 = lastpathfindpoint;
7679 if (lastpathfindpoint3 == -1) {
7680 lastpathfindpoint3 = lastpathfindpoint2;
7682 if (lastpathfindpoint4 == -1) {
7683 lastpathfindpoint4 = lastpathfindpoint3;
7685 targetpathfindpoint = -1;
7687 if (distsqflat(&coords, &finalfinaltarget) <
7688 distsqflat(&coords, &finaltarget) ||
7689 distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) ||
7690 lastpathfindpoint == finalpathfindpoint) {
7691 aitype = passivetype;
7702 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7703 targetyaw += 90 * (whichdirection * 2 - 1);
7706 if (collided < 1 || animTarget != jumpupanim) {
7709 if ((collided > .8 && jumppower >= 5)) {
7713 if ((!Tutorial::active || cananger) &&
7715 !Person::players[0]->dead &&
7716 distsq(&coords, &Person::players[0]->coords) < 400 &&
7718 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7719 Animation::animations[Person::players[0]->animTarget].height != lowheight &&
7720 !Game::editorenabled &&
7721 (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain)) {
7722 aitype = attacktypecutoff;
7724 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7725 Animation::animations[Person::players[0]->animTarget].height == highheight &&
7726 !Game::editorenabled) {
7727 aitype = attacktypecutoff;
7730 if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7731 losupdatedelay = .2;
7732 for (unsigned j = 0; j < Person::players.size(); j++) {
7733 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7734 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7735 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7736 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7737 if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain) {
7738 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) ||
7739 (Person::players[j]->animTarget == hanganim &&
7740 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7741 aitype = searchtype;
7743 lastseen = Person::players[j]->coords;
7754 if (aitype == attacktypecutoff && Game::musictype != 2) {
7755 if (creature != wolftype) {
7762 if (aitype != passivetype && Game::leveltime > .5) {
7763 howactive = typeactive;
7766 if (aitype == passivetype) {
7767 aiupdatedelay -= multiplier;
7768 losupdatedelay -= multiplier;
7769 lastseentime += multiplier;
7770 pausetime -= multiplier;
7771 if (lastseentime > 1) {
7775 if (aiupdatedelay < 0) {
7776 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7777 targetyaw = roughDirectionTo(coords, waypoints[waypoint]);
7778 lookyaw = targetyaw;
7779 aiupdatedelay = .05;
7781 if (distsqflat(&coords, &waypoints[waypoint]) < 1) {
7782 if (waypointtype[waypoint] == wppause) {
7786 if (waypoint > numwaypoints - 1) {
7792 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7804 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7805 if (!avoidsomething) {
7806 targetyaw += 90 * (whichdirection * 2 - 1);
7808 XYZ leftpos, rightpos;
7809 float leftdist, rightdist;
7810 leftpos = coords + DoRotation(facing, 0, 90, 0);
7811 rightpos = coords - DoRotation(facing, 0, 90, 0);
7812 leftdist = distsq(&leftpos, &avoidwhere);
7813 rightdist = distsq(&rightpos, &avoidwhere);
7814 if (leftdist < rightdist) {
7822 if (collided < 1 || animTarget != jumpupanim) {
7825 if ((collided > .8 && jumppower >= 5)) {
7830 if (!Game::editorenabled) {
7831 if (howactive <= typesleeping) {
7832 if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile) {
7833 for (int j = 0; j < numenvsounds; j++) {
7834 float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
7835 if (vol > 0 && distsq(&coords, &envsound[j]) < 2 * (vol + vol * (creature == rabbittype) * 3)) {
7836 aitype = attacktypecutoff;
7842 if (aitype != passivetype) {
7843 if (howactive == typesleeping) {
7844 setTargetAnimation(getupfromfrontanim);
7846 howactive = typeactive;
7850 if (howactive < typesleeping &&
7851 ((!Tutorial::active || cananger) && hostile) &&
7852 !Person::players[0]->dead &&
7853 distsq(&coords, &Person::players[0]->coords) < 400 &&
7855 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7856 Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled) {
7857 aitype = attacktypecutoff;
7859 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7860 Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled) {
7861 aitype = attacktypecutoff;
7865 if (creature == wolftype) {
7867 for (unsigned j = 0; j < Person::players.size(); j++) {
7868 if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
7869 float smelldistance = 50;
7870 if (j == 0 && Person::players[j]->num_weapons > 0) {
7871 if (weapons[Person::players[j]->weaponids[0]].bloody) {
7872 smelldistance = 100;
7874 if (Person::players[j]->num_weapons == 2) {
7875 if (weapons[Person::players[j]->weaponids[1]].bloody) {
7876 smelldistance = 100;
7881 smelldistance = 100;
7883 windsmell = windvector;
7884 Normalise(&windsmell);
7885 windsmell = windsmell * 2 + Person::players[j]->coords;
7886 if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled) {
7887 aitype = attacktypecutoff;
7893 if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7894 losupdatedelay = .2;
7895 for (unsigned j = 0; j < Person::players.size(); j++) {
7896 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7897 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7898 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7899 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7900 if ((-1 == Object::checkcollide(
7901 DoRotation(jointPos(head), 0, yaw, 0) *
7904 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0) *
7905 Person::players[j]->scale +
7906 Person::players[j]->coords) &&
7907 !Person::players[j]->isWallJump()) ||
7908 (Person::players[j]->animTarget == hanganim &&
7909 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7911 if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight) {
7920 if (lastseentime <= 0) {
7921 aitype = searchtype;
7923 lastseen = Person::players[j]->coords;
7931 if (aitype == attacktypecutoff && Game::musictype != 2) {
7932 if (creature != wolftype) {
7936 if (creature == wolftype) {
7946 if (aitype == searchtype) {
7947 aiupdatedelay -= multiplier;
7948 losupdatedelay -= multiplier;
7950 lastseentime -= multiplier;
7952 lastchecktime -= multiplier;
7954 if (isRun() && !onground) {
7955 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7956 XYZ test2 = coords + facing;
7958 XYZ test = coords + facing;
7960 j = Object::checkcollide(test2, test, laststanding);
7962 j = Object::checkcollide(test2, test);
7966 setTargetAnimation(getStop());
7969 //aitype=passivetype;
7970 aitype = pathfindtype;
7971 finalfinaltarget = waypoints[waypoint];
7972 finalpathfindpoint = -1;
7973 targetpathfindpoint = -1;
7974 lastpathfindpoint = -1;
7975 lastpathfindpoint2 = -1;
7976 lastpathfindpoint3 = -1;
7977 lastpathfindpoint4 = -1;
7983 //check out last seen location
7984 if (aiupdatedelay < 0) {
7985 targetyaw = roughDirectionTo(coords, lastseen);
7986 lookyaw = targetyaw;
7987 aiupdatedelay = .05;
7990 if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) {
7993 lastseen.x += (float(Random() % 100) - 50) / 25;
7994 lastseen.z += (float(Random() % 100) - 50) / 25;
8005 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8006 if (!avoidsomething) {
8007 targetyaw += 90 * (whichdirection * 2 - 1);
8009 XYZ leftpos, rightpos;
8010 float leftdist, rightdist;
8011 leftpos = coords + DoRotation(facing, 0, 90, 0);
8012 rightpos = coords - DoRotation(facing, 0, 90, 0);
8013 leftdist = distsq(&leftpos, &avoidwhere);
8014 rightdist = distsq(&rightpos, &avoidwhere);
8015 if (leftdist < rightdist) {
8023 if (collided < 1 || animTarget != jumpupanim) {
8026 if ((collided > .8 && jumppower >= 5)) {
8030 if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile)) {
8031 for (int k = 0; k < numenvsounds; k++) {
8032 if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) {
8033 aitype = attacktypecutoff;
8038 if (!Person::players[0]->dead &&
8039 losupdatedelay < 0 &&
8040 !Game::editorenabled &&
8042 ((!Tutorial::active || cananger) && hostile)) {
8043 losupdatedelay = .2;
8044 if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) {
8045 aitype = attacktypecutoff;
8048 if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight) {
8049 //TODO: factor out canSeePlayer()
8050 if (distsq(&coords, &Person::players[0]->coords) < 400) {
8051 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
8052 if ((Object::checkcollide(
8053 DoRotation(jointPos(head), 0, yaw, 0) *
8056 DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0) *
8057 Person::players[0]->scale +
8058 Person::players[0]->coords) == -1) ||
8059 (Person::players[0]->animTarget == hanganim && normaldotproduct(Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) {
8060 /* //TODO: changed j to 0 on a whim, make sure this is correct
8061 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
8062 Person::players[j]->facing,coords-Person::players[j]->coords)<0)
8064 aitype = attacktypecutoff;
8072 if (lastseentime < 0) {
8073 //aitype=passivetype;
8075 aitype = pathfindtype;
8076 finalfinaltarget = waypoints[waypoint];
8077 finalpathfindpoint = -1;
8078 targetpathfindpoint = -1;
8079 lastpathfindpoint = -1;
8080 lastpathfindpoint2 = -1;
8081 lastpathfindpoint3 = -1;
8082 lastpathfindpoint4 = -1;
8086 if (aitype != gethelptype) {
8090 //get help from buddies
8091 if (aitype == gethelptype) {
8092 runninghowlong += multiplier;
8093 aiupdatedelay -= multiplier;
8095 if (aiupdatedelay < 0 || ally == 0) {
8099 //TODO: factor out closest search somehow
8102 float closestdist = -1;
8103 for (unsigned k = 0; k < Person::players.size(); k++) {
8104 if ((k != id) && (k != 0) && !Person::players[k]->dead &&
8105 (Person::players[k]->howactive < typedead1) &&
8106 !Person::players[k]->skeleton.free &&
8107 (Person::players[k]->aitype == passivetype)) {
8108 float distance = distsq(&coords, &Person::players[k]->coords);
8109 if (closestdist == -1 || distance < closestdist) {
8110 closestdist = distance;
8115 if (closest != -1) {
8120 lastseen = Person::players[0]->coords;
8126 XYZ facing = coords;
8127 XYZ flatfacing = Person::players[ally]->coords;
8128 facing.y += jointPos(head).y * scale;
8129 flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale;
8130 if (-1 != Object::checkcollide(facing, flatfacing)) {
8134 //no available ally, run back to player
8136 Person::players[ally]->skeleton.free ||
8137 Person::players[ally]->aitype != passivetype ||
8138 lastseentime <= 0) {
8139 aitype = searchtype;
8145 targetyaw = roughDirectionTo(coords, Person::players[ally]->coords);
8146 lookyaw = targetyaw;
8147 aiupdatedelay = .05;
8150 if (distsqflat(&coords, &Person::players[ally]->coords) < 3) {
8151 aitype = searchtype;
8153 Person::players[ally]->aitype = searchtype;
8154 if (Person::players[ally]->lastseentime < lastseentime) {
8155 Person::players[ally]->lastseen = lastseen;
8156 Person::players[ally]->lastseentime = lastseentime;
8157 Person::players[ally]->lastchecktime = lastchecktime;
8161 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8162 if (!avoidsomething) {
8163 targetyaw += 90 * (whichdirection * 2 - 1);
8165 XYZ leftpos, rightpos;
8166 float leftdist, rightdist;
8167 leftpos = coords + DoRotation(facing, 0, 90, 0);
8168 rightpos = coords - DoRotation(facing, 0, 90, 0);
8169 leftdist = distsq(&leftpos, &avoidwhere);
8170 rightdist = distsq(&rightpos, &avoidwhere);
8171 if (leftdist < rightdist) {
8186 if (collided < 1 || animTarget != jumpupanim) {
8189 if (collided > .8 && jumppower >= 5) {
8194 //retreiving a weapon on the ground
8195 if (aitype == getweapontype) {
8196 aiupdatedelay -= multiplier;
8197 lastchecktime -= multiplier;
8199 if (aiupdatedelay < 0) {
8205 float closestdist = -1;
8206 for (unsigned k = 0; k < weapons.size(); k++) {
8207 if (weapons[k].owner == -1) {
8208 float distance = distsq(&coords, &weapons[k].position);
8209 if (closestdist == -1 || distance < closestdist) {
8210 closestdist = distance;
8215 if (closest != -1) {
8224 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile)) {
8225 if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) {
8226 aitype = attacktypecutoff;
8230 if (!Person::players[0]->dead) {
8232 if (weapons[ally].owner != -1 ||
8233 distsq(&coords, &weapons[ally].position) > 16) {
8234 aitype = attacktypecutoff;
8237 //TODO: factor these out as moveToward()
8238 targetyaw = roughDirectionTo(coords, weapons[ally].position);
8239 lookyaw = targetyaw;
8240 aiupdatedelay = .05;
8243 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8244 if (!avoidsomething) {
8245 targetyaw += 90 * (whichdirection * 2 - 1);
8247 XYZ leftpos, rightpos;
8248 float leftdist, rightdist;
8249 leftpos = coords + DoRotation(facing, 0, 90, 0);
8250 rightpos = coords - DoRotation(facing, 0, 90, 0);
8251 leftdist = distsq(&leftpos, &avoidwhere);
8252 rightdist = distsq(&rightpos, &avoidwhere);
8253 if (leftdist < rightdist) {
8269 if (animTarget != crouchremoveknifeanim &&
8270 animTarget != removeknifeanim) {
8271 throwtogglekeydown = 0;
8275 if (collided < 1 || animTarget != jumpupanim) {
8278 if ((collided > .8 && jumppower >= 5)) {
8283 if (aitype == attacktypecutoff) {
8284 aiupdatedelay -= multiplier;
8285 //dodge or reverse rabbit kicks, knife throws, flips
8286 if (damage < damagetolerance * 2 / 3) {
8287 if ((Person::players[0]->animTarget == rabbitkickanim ||
8288 Person::players[0]->animTarget == knifethrowanim ||
8289 (Person::players[0]->isFlip() &&
8290 normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) &&
8291 !Person::players[0]->skeleton.free &&
8292 (aiupdatedelay < .1)) {
8297 if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
8298 if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
8299 if (isIdle() || isCrouch() || isRun() || isFlip()) {
8300 if (abs(Random() % 2) == 0) {
8301 setTargetAnimation(backhandspringanim);
8303 setTargetAnimation(rollanim);
8305 targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
8308 if (animTarget == jumpupanim || animTarget == jumpdownanim) {
8309 setTargetAnimation(flipanim);
8314 aiupdatedelay = .02;
8317 //get confused by flips
8318 if (Person::players[0]->isFlip() &&
8319 !Person::players[0]->skeleton.free &&
8320 Person::players[0]->animTarget != walljumprightkickanim &&
8321 Person::players[0]->animTarget != walljumpleftkickanim) {
8322 if (distsq(&Person::players[0]->coords, &coords) < 25) {
8323 if ((1 - damage / damagetolerance) > .5) {
8328 //go for weapon on the ground
8329 if (wentforweapon < 3) {
8330 for (unsigned k = 0; k < weapons.size(); k++) {
8331 if (creature != wolftype) {
8332 if (num_weapons == 0 &&
8333 weapons[k].owner == -1 &&
8334 weapons[k].velocity.x == 0 &&
8335 weapons[k].velocity.z == 0 &&
8336 weapons[k].velocity.y == 0) {
8337 if (distsq(&coords, &weapons[k].position) < 16) {
8340 aitype = getweapontype;
8347 //dodge/reverse walljump kicks
8348 if (damage < damagetolerance / 2) {
8349 if (Animation::animations[animTarget].height != highheight) {
8350 if (damage < damagetolerance * .5 &&
8351 ((Person::players[0]->animTarget == walljumprightkickanim ||
8352 Person::players[0]->animTarget == walljumpleftkickanim) &&
8353 ((aiupdatedelay < .15 &&
8355 (aiupdatedelay < .08 &&
8356 difficulty != 2)))) {
8361 //walked off a ledge (?)
8362 if (isRun() && !onground) {
8363 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
8364 XYZ test2 = coords + facing;
8366 XYZ test = coords + facing;
8368 j = Object::checkcollide(test2, test, laststanding);
8370 j = Object::checkcollide(test2, test);
8374 setTargetAnimation(getStop());
8377 aitype = pathfindtype;
8378 finalfinaltarget = waypoints[waypoint];
8379 finalpathfindpoint = -1;
8380 targetpathfindpoint = -1;
8381 lastpathfindpoint = -1;
8382 lastpathfindpoint2 = -1;
8383 lastpathfindpoint3 = -1;
8384 lastpathfindpoint4 = -1;
8390 //lose sight of player in the air (?)
8391 if (Person::players[0]->coords.y > coords.y + 5 &&
8392 Animation::animations[Person::players[0]->animTarget].height != highheight &&
8393 !Person::players[0]->onterrain) {
8394 aitype = pathfindtype;
8395 finalfinaltarget = waypoints[waypoint];
8396 finalpathfindpoint = -1;
8397 targetpathfindpoint = -1;
8398 lastpathfindpoint = -1;
8399 lastpathfindpoint2 = -1;
8400 lastpathfindpoint3 = -1;
8401 lastpathfindpoint4 = -1;
8403 //it's time to think (?)
8404 if (aiupdatedelay < 0 &&
8405 !Animation::animations[animTarget].attack &&
8406 animTarget != staggerbackhighanim &&
8407 animTarget != staggerbackhardanim &&
8408 animTarget != backhandspringanim &&
8409 animTarget != dodgebackanim) {
8411 if (weaponactive == -1 && num_weapons > 0) {
8412 drawkeydown = Random() % 2;
8416 rabbitkickenabled = Random() % 2;
8418 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
8419 XYZ targetpoint = Person::players[0]->coords;
8420 float vellength = findLength(&velocity);
8421 if (vellength != 0 &&
8422 distsq(&Person::players[0]->coords, &coords) < distsq(&rotatetarget, &coords)) {
8423 targetpoint += Person::players[0]->velocity *
8424 findDistance(&Person::players[0]->coords, &coords) / vellength;
8426 targetyaw = roughDirectionTo(coords, targetpoint);
8427 lookyaw = targetyaw;
8428 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
8430 if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1)) {
8432 } else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
8433 distsq(&coords, &Person::players[0]->coords) < 9) &&
8434 Person::players[0]->weaponactive != -1) {
8436 } else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0)) {
8441 //chill out around the corpse
8442 if (Person::players[0]->dead) {
8444 if (Random() % 10 == 0) {
8447 if (Random() % 100 == 0) {
8448 aitype = pathfindtype;
8449 finalfinaltarget = waypoints[waypoint];
8450 finalpathfindpoint = -1;
8451 targetpathfindpoint = -1;
8452 lastpathfindpoint = -1;
8453 lastpathfindpoint2 = -1;
8454 lastpathfindpoint3 = -1;
8455 lastpathfindpoint4 = -1;
8464 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8465 targetyaw += 90 * (whichdirection * 2 - 1);
8468 if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype) {
8473 if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7) {
8478 if (aitype != playercontrolled &&
8483 for (unsigned j = 0; j < Person::players.size(); j++) {
8484 if (j != id && !Person::players[j]->skeleton.free &&
8485 Person::players[j]->hasvictim &&
8486 (Tutorial::active && reversaltrain ||
8487 Random() % 2 == 0 && difficulty == 2 ||
8488 Random() % 4 == 0 && difficulty == 1 ||
8489 Random() % 8 == 0 && difficulty == 0 ||
8490 Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
8491 Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
8492 (Random() % 2 == 0 || difficulty == 2) ||
8493 (isIdle() || isRun()) &&
8494 Person::players[j]->weaponactive != -1 ||
8495 Person::players[j]->animTarget == swordslashanim &&
8496 weaponactive != -1 ||
8497 Person::players[j]->animTarget == staffhitanim ||
8498 Person::players[j]->animTarget == staffspinhitanim)) {
8499 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
8500 Person::players[j]->victim == Person::players[id] &&
8501 (Person::players[j]->animTarget == sweepanim ||
8502 Person::players[j]->animTarget == spinkickanim ||
8503 Person::players[j]->animTarget == staffhitanim ||
8504 Person::players[j]->animTarget == staffspinhitanim ||
8505 Person::players[j]->animTarget == winduppunchanim ||
8506 Person::players[j]->animTarget == upunchanim ||
8507 Person::players[j]->animTarget == wolfslapanim ||
8508 Person::players[j]->animTarget == knifeslashstartanim ||
8509 Person::players[j]->animTarget == swordslashanim &&
8510 (distsq(&Person::players[j]->coords, &coords) < 2 ||
8511 weaponactive != -1))) {
8521 Person::players[target]->Reverse();
8528 if (collided > .8 && jumppower >= 5 ||
8529 distsq(&coords, &Person::players[0]->coords) > 400 &&
8531 creature == rabbittype) {
8534 //TODO: why are we controlling the human?
8535 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
8536 Person::players[0]->jumpkeydown = 0;
8538 if (Person::players[0]->animTarget == jumpdownanim &&
8539 distsq(&Person::players[0]->coords, &coords) < 40) {
8546 if (Tutorial::active) {
8552 XYZ facing = coords;
8553 XYZ flatfacing = Person::players[0]->coords;
8554 facing.y += jointPos(head).y * scale;
8555 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
8556 if (occluded >= 2) {
8557 if (-1 != Object::checkcollide(facing, flatfacing)) {
8561 if (lastseentime <= 0 &&
8562 (creature != wolftype ||
8563 weaponstuck == -1)) {
8564 aitype = searchtype;
8566 lastseen = Person::players[0]->coords;
8575 if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
8576 (aitype == attacktypecutoff ||
8577 aitype == searchtype)) {
8578 if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
8579 XYZ test = Person::players[0]->coords;
8581 if (-1 == Object::checkcollide(Person::players[0]->coords, test)) {
8587 if (aitype == passivetype && !(numwaypoints > 1) ||
8589 pause && damage > superpermanentdamage) {
8608 XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0);
8609 facing = flatfacing;
8611 if (aitype == attacktypecutoff) {
8612 targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
8613 targetheadpitch = pitchTo(coords, Person::players[0]->coords);
8614 } else if (howactive >= typesleeping) {
8615 targetheadyaw = targetyaw;
8616 targetheadpitch = 0;
8618 if (interestdelay <= 0) {
8619 interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
8620 headtarget = coords;
8621 headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
8622 headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
8623 headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
8624 headtarget += facing * 1.5;
8626 targetheadyaw = 180 - roughDirectionTo(coords, headtarget);
8627 targetheadpitch = pitchTo(coords, headtarget);