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()
84 types[wolftype].proportions[0] = 1.1;
85 types[wolftype].proportions[1] = 1.1;
86 types[wolftype].proportions[2] = 1.1;
87 types[wolftype].proportions[3] = 1.1;
89 types[rabbittype].proportions[0] = 1.2;
90 types[rabbittype].proportions[1] = 1.05;
91 types[rabbittype].proportions[2] = 1;
92 types[rabbittype].proportions[3] = 1.1;
93 types[rabbittype].proportions[3].y = 1.05;
99 , animCurrent(bounceidleanim)
100 , animTarget(bounceidleanim)
107 , howactive(typeactive)
109 , superruntoggle(false)
143 , rabbitkickenabled(false)
157 , superpermanentdamage(0)
200 , normalsupdatedelay(0)
204 , forwardkeydown(false)
205 , forwardstogglekeydown(false)
206 , rightkeydown(false)
210 , jumptogglekeydown(false)
211 , crouchkeydown(false)
212 , crouchtogglekeydown(false)
214 , drawtogglekeydown(false)
215 , throwkeydown(false)
216 , throwtogglekeydown(false)
217 , attackkeydown(false)
239 , whichdirection(false)
240 , whichdirectiondelay(0)
241 , avoidsomething(false)
251 , lefthandmorphness(0)
252 , righthandmorphness(0)
256 , targetlefthandmorphness(0)
257 , targetrighthandmorphness(0)
258 , targetheadmorphness(1)
259 , targetchestmorphness(0)
260 , targettailmorphness(0)
261 , lefthandmorphstart(0)
262 , lefthandmorphend(0)
263 , righthandmorphstart(0)
264 , righthandmorphend(0)
274 , highreversaldelay(0)
275 , lowreversaldelay(0)
324 , weaponstuckwhere(0)
337 , finalpathfindpoint(0)
338 , targetpathfindpoint(0)
339 , lastpathfindpoint(0)
340 , lastpathfindpoint2(0)
341 , lastpathfindpoint3(0)
342 , lastpathfindpoint4(0)
362 , neckspurtparticledelay(0)
367 , rabbitkickragdoll(false)
375 setProportions(1, 1, 1, 1);
378 /* Read a person in tfile. Throws an error if it’s not valid */
379 Person::Person(FILE* tfile, int mapvers, unsigned i)
383 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
385 funpackf(tfile, "Bi", &howactive);
387 howactive = typeactive;
390 funpackf(tfile, "Bf", &scale);
395 funpackf(tfile, "Bb", &immobile);
400 funpackf(tfile, "Bf", &yaw);
405 if (num_weapons < 0 || num_weapons > 5) {
406 throw InvalidPersonException();
408 if (num_weapons > 0 && num_weapons < 5) {
409 for (int j = 0; j < num_weapons; j++) {
410 weaponids[j] = weapons.size();
412 funpackf(tfile, "Bi", &type);
413 weapons.push_back(Weapon(type, id));
416 funpackf(tfile, "Bi", &numwaypoints);
417 for (int j = 0; j < numwaypoints; j++) {
418 funpackf(tfile, "Bf", &waypoints[j].x);
419 funpackf(tfile, "Bf", &waypoints[j].y);
420 funpackf(tfile, "Bf", &waypoints[j].z);
422 funpackf(tfile, "Bi", &waypointtype[j]);
424 waypointtype[j] = wpkeepwalking;
428 funpackf(tfile, "Bi", &waypoint);
429 if (waypoint > (numwaypoints - 1)) {
433 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
434 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
435 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
436 funpackf(tfile, "Bf Bf", &power, &speedmult);
439 funpackf(tfile, "Bf Bf Bf Bf", &proportions[0], &proportions[1], &proportions[2], &proportions[3]);
441 setProportions(1, 1, 1, 1);
444 funpackf(tfile, "Bi", &numclothes);
445 for (int k = 0; k < numclothes; k++) {
447 funpackf(tfile, "Bi", &templength);
448 for (int l = 0; l < templength; l++) {
449 funpackf(tfile, "Bb", &clothes[k][l]);
451 clothes[k][templength] = '\0';
452 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
458 if (creature == wolftype) {
460 damagetolerance = 300;
467 realoldcoords = coords;
470 void Person::skeletonLoad(bool clothes)
473 if (creature != wolftype) {
475 "Skeleton/BasicFigure",
476 "Skeleton/BasicFigureLow",
477 "Skeleton/RabbitBelt",
479 "Models/Body2.solid",
480 "Models/Body3.solid",
481 "Models/Body4.solid",
482 "Models/Body5.solid",
483 "Models/Body6.solid",
484 "Models/Body7.solid",
485 "Models/BodyLow.solid",
490 "Skeleton/BasicFigureWolf",
491 "Skeleton/BasicFigureWolfLow",
492 "Skeleton/RabbitBelt",
494 "Models/Wolf2.solid",
495 "Models/Wolf3.solid",
496 "Models/Wolf4.solid",
497 "Models/Wolf5.solid",
498 "Models/Wolf6.solid",
499 "Models/Wolf7.solid",
500 "Models/WolfLow.solid",
505 skeleton.drawmodel.textureptr.load(creatureskin[creature][whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
508 void Person::setProportions(float head, float body, float arms, float legs)
510 proportions[0] = head;
511 proportions[1] = body;
512 proportions[2] = arms;
513 proportions[3] = legs;
516 XYZ Person::getProportion(int part) const
518 XYZ prop = PersonType::types[creature].proportions[part] * proportions[part];
528 * GameTick/doPlayerCollisions
530 void Person::CheckKick()
532 if (!(hasvictim && (animTarget == rabbitkickanim && victim && victim != this->shared_from_this() && frameCurrent >= 2 && animCurrent == rabbitkickanim) && distsq(&coords, &victim->coords) < 1.2 && !victim->skeleton.free)) {
536 if (Animation::animations[victim->animTarget].height != lowheight) {
537 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
538 XYZ relative = velocity;
540 Normalise(&relative);
544 if (!Tutorial::active) {
545 emit_sound_at(heavyimpactsound, victim->coords);
548 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
549 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
552 victim->DoDamage(100 * damagemult / victim->protectionhigh);
559 animTarget = backflipanim;
561 velocity = facing * -10;
565 resume_stream(whooshsound);
568 award_bonus(id, cannon);
569 } else if (victim->isCrouch()) {
570 animTarget = rabbitkickreversedanim;
571 animCurrent = rabbitkickreversedanim;
572 victim->animCurrent = rabbitkickreversalanim;
573 victim->animTarget = rabbitkickreversalanim;
579 victim->oldcoords = victim->coords;
580 coords = victim->coords;
581 victim->targetyaw = targetyaw;
582 victim->victim = this->shared_from_this();
589 * GameTick::doPlayerCollisions - spread fire between players
590 * GameTick::ProcessDevKeys - press f to ignite
591 * Person::DoStuff - spread fire from lit campfires and bushes
593 void Person::CatchFire()
595 XYZ flatfacing, flatvelocity;
597 for (int i = 0; i < 10; i++) {
598 howmany = fabs(Random() % (skeleton.joints.size()));
600 flatvelocity = skeleton.joints[howmany].velocity;
601 flatfacing = skeleton.joints[howmany].position * scale + coords;
603 flatvelocity = velocity;
604 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
606 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
611 emit_sound_at(firestartsound, coords);
613 emit_stream_at(stream_firesound, coords);
621 * idle animation for this creature (depending on status)
623 int Person::getIdle()
625 if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype)) {
628 if (hasvictim && (victim != this->shared_from_this())) {
629 if ((!victim->dead && victim->aitype != passivetype &&
630 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
631 victim->id < Person::players.size())) {
632 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
633 if (creature == rabbittype) {
634 return fightidleanim;
636 if (creature == wolftype) {
640 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
641 if (weapons[weaponids[weaponactive]].getType() == knife) {
642 return knifefightidleanim;
644 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1) {
645 return swordfightidlebothanim;
647 if (weapons[weaponids[weaponactive]].getType() == sword) {
648 return swordfightidleanim;
650 if (weapons[weaponids[weaponactive]].getType() == staff) {
651 return swordfightidleanim;
654 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause) {
655 return fightsidestep;
659 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype) {
662 if (howactive == typesitting) {
665 if (howactive == typesittingwall) {
668 if (howactive == typesleeping) {
671 if (howactive == typedead1) {
674 if (howactive == typedead2) {
677 if (howactive == typedead3) {
680 if (howactive == typedead4) {
683 if (creature == rabbittype) {
684 return bounceidleanim;
686 if (creature == wolftype) {
693 * crouch animation for this creature
695 int Person::getCrouch()
697 if (creature == rabbittype) {
700 if (creature == wolftype) {
701 return wolfcrouchanim;
707 * running animation for this creature (can be upright or all fours)
711 if (creature == rabbittype && (!superruntoggle || weaponactive != -1)) {
714 if (creature == wolftype && (!superruntoggle)) {
718 if (creature == rabbittype && (superruntoggle && weaponactive == -1)) {
719 return rabbitrunninganim;
721 if (creature == wolftype && (superruntoggle)) {
722 return wolfrunninganim;
729 int Person::getStop()
731 if (creature == rabbittype) {
734 if (creature == wolftype) {
742 int Person::getLanding()
744 if (creature == rabbittype) {
747 if (creature == wolftype) {
755 int Person::getLandhard()
757 if (creature == rabbittype) {
760 if (creature == wolftype) {
761 return wolflandhardanim;
769 * Person::DoAnimations
772 SolidHitBonus(int playerid)
774 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo) {
775 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
777 award_bonus(playerid, solidhit);
782 * spawns blood effects
784 void Person::DoBlood(float howmuch, int which)
786 // FIXME: should abstract out inputs
787 static int bleedxint, bleedyint;
789 if (bloodtoggle && !Tutorial::active) {
790 if (bleeding <= 0 && spurt) {
792 for (int i = 0; i < 3; i++) {
793 // emit blood particles
796 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
797 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
798 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
799 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
802 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
803 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
804 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
805 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
808 if (Random() % 2 == 0) { // 50% chance
809 for (int i = 0; i < 3; i++) {
810 if (Random() % 2 != 0) {
811 // emit teeth particles
814 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
815 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
818 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
819 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
823 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
825 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
827 Sprite::setLastSpriteSpecial(3); // sets it to teeth
833 // FIXME: manipulating attributes
834 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
837 if (creature == rabbittype) {
838 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) {
839 bleedxint = abs(Random() % 512);
840 bleedyint = abs(Random() % 512);
843 if (creature == wolftype) {
844 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) {
845 bleedxint = abs(Random() % 512);
846 bleedyint = abs(Random() % 512);
851 bleedy /= realtexdetail;
852 bleedx /= realtexdetail;
853 direction = abs(Random() % 2) * 2 - 1;
862 * spawns big blood effects and ???
863 * modifies character's skin texture
865 void Person::DoBloodBig(float howmuch, int which)
867 static int bleedxint, bleedyint, i, j;
869 if (howmuch && id == 0) {
873 if (!Tutorial::active || id == 0) {
874 if (aitype != playercontrolled && howmuch > 0) {
878 if (creature == wolftype) {
879 int i = abs(Random() % 2);
881 whichsound = snarlsound;
884 whichsound = snarl2sound;
887 if (creature == rabbittype) {
888 int i = abs(Random() % 2);
890 whichsound = rabbitpainsound;
892 if (i == 1 && howmuch >= 2) {
893 whichsound = rabbitpain1sound;
897 if (whichsound != -1) {
898 emit_sound_at(whichsound, coords);
904 if (id == 0 && howmuch > 0) {
908 if (bloodtoggle && decalstoggle && !Tutorial::active) {
909 if (bleeding <= 0 && spurt) {
911 for (int i = 0; i < 3; i++) {
912 // emit blood particles
913 // FIXME: copypaste from above
916 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
917 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
918 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
919 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
922 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
923 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
924 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
925 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
930 // weird texture manipulation code follows.
931 // looks like this is painting blood onto the character's skin texture
932 // FIXME: surely there's a better way
934 int offsetx = 0, offsety = 0;
936 offsety = Random() % 40;
937 offsetx = abs(Random() % 60);
939 if (which == 190 || which == 185) {
940 offsety = Random() % 40;
941 offsetx = abs(Random() % 100) - 20;
944 offsety = Random() % 10;
945 offsetx = Random() % 10;
948 offsety = Random() % 20;
949 offsetx = Random() % 20;
951 if (which == 220 || which == 215) {
960 if (creature == rabbittype) {
961 for (i = 0; i < 512; i++) {
962 for (j = 0; j < 512; j++) {
963 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
980 if (creature == wolftype) {
981 for (i = 0; i < 512; i++) {
982 for (j = 0; j < 512; j++) {
983 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1012 if (endx > 512 - 1) {
1015 if (endy > 512 - 1) {
1018 if (endx < startx) {
1021 if (endy < starty) {
1025 startx /= realtexdetail;
1026 starty /= realtexdetail;
1027 endx /= realtexdetail;
1028 endy /= realtexdetail;
1030 int texdetailint = realtexdetail;
1032 if (creature == rabbittype) {
1033 for (i = startx; i < endx; i++) {
1034 for (j = starty; j < endy; j++) {
1035 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) {
1036 color = Random() % 85 + 170;
1037 where = i * skeleton.skinsize * 3 + j * 3;
1038 if (skeleton.skinText[where + 0] > color / 2) {
1039 skeleton.skinText[where + 0] = color / 2;
1041 skeleton.skinText[where + 1] = 0;
1042 skeleton.skinText[where + 2] = 0;
1047 if (creature == wolftype) {
1048 for (i = startx; i < endx; i++) {
1049 for (j = starty; j < endy; j++) {
1050 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) {
1051 color = Random() % 85 + 170;
1052 where = i * skeleton.skinsize * 3 + j * 3;
1053 if (skeleton.skinText[where + 0] > color / 2) {
1054 skeleton.skinText[where + 0] = color / 2;
1056 skeleton.skinText[where + 1] = 0;
1057 skeleton.skinText[where + 2] = 0;
1062 skeleton.drawmodel.textureptr.bind();
1067 if (creature == rabbittype) {
1068 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) {
1069 bleedxint = abs(Random() % 512);
1070 bleedyint = abs(Random() % 512);
1073 if (creature == wolftype) {
1074 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) {
1075 bleedxint = abs(Random() % 512);
1076 bleedyint = abs(Random() % 512);
1079 bleedy = bleedxint + offsetx;
1080 bleedx = bleedyint + offsety;
1081 bleedy /= realtexdetail;
1082 bleedx /= realtexdetail;
1089 if (bleedx > skeleton.skinsize - 1) {
1090 bleedx = skeleton.skinsize - 1;
1092 if (bleedy > skeleton.skinsize - 1) {
1093 bleedy = skeleton.skinsize - 1;
1095 direction = abs(Random() % 2) * 2 - 1;
1097 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1098 deathbleeding += bleeding;
1099 bloodloss += bleeding * 3;
1101 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1102 if (abs(Random() % 2) == 0) {
1103 aitype = gethelptype;
1106 aitype = attacktypecutoff;
1116 * similar to DoBloodBig
1118 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
1121 static XYZ bloodvel;
1122 static XYZ startpoint, endpoint, colpoint, movepoint;
1123 static float rotationpoint;
1124 static int whichtri;
1125 static XYZ p1, p2, p3, p0;
1128 float coordsx, coordsy;
1131 if (bloodtoggle && decalstoggle && !Tutorial::active) {
1133 if (!skeleton.free) {
1134 where = DoRotation(where, 0, -yaw, 0);
1138 startpoint.y += 100;
1143 // ray testing for a tri in the character model
1144 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
1145 if (whichtri != -1) {
1146 // low level geometry math
1148 p1 = skeleton.drawmodel.getTriangleVertex(whichtri, 0);
1149 p2 = skeleton.drawmodel.getTriangleVertex(whichtri, 1);
1150 p3 = skeleton.drawmodel.getTriangleVertex(whichtri, 2);
1152 bary.x = distsq(&p0, &p1);
1153 bary.y = distsq(&p0, &p2);
1154 bary.z = distsq(&p0, &p3);
1156 total = bary.x + bary.y + bary.z;
1161 bary.x = 1 - bary.x;
1162 bary.y = 1 - bary.y;
1163 bary.z = 1 - bary.z;
1165 total = bary.x + bary.y + bary.z;
1170 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1171 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1172 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1173 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1174 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1175 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1176 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;
1177 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;
1179 if (bleeding <= 0 && spurt) {
1181 for (int i = 0; i < 3; i++) {
1182 // emit blood particles
1183 // FIXME: more copypaste code
1185 if (skeleton.free) {
1186 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1187 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1188 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1189 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1192 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1193 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1194 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1195 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1200 // texture manipulation follows
1202 int offsetx = 0, offsety = 0;
1203 offsetx = (1 + coordsy) * 512 - 291;
1204 offsety = coordsx * 512 - 437;
1211 if (creature == rabbittype) {
1212 for (i = 0; i < 512; i++) {
1213 for (j = 0; j < 512; j++) {
1214 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1231 if (creature == wolftype) {
1232 for (i = 0; i < 512; i++) {
1233 for (j = 0; j < 512; j++) {
1234 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1262 if (endx > 512 - 1) {
1265 if (endy > 512 - 1) {
1268 if (endx < startx) {
1271 if (endy < starty) {
1275 startx /= realtexdetail;
1276 starty /= realtexdetail;
1277 endx /= realtexdetail;
1278 endy /= realtexdetail;
1280 int texdetailint = realtexdetail;
1282 if (creature == rabbittype) {
1283 for (i = startx; i < endx; i++) {
1284 for (j = starty; j < endy; j++) {
1285 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) {
1286 color = Random() % 85 + 170;
1287 where = i * skeleton.skinsize * 3 + j * 3;
1288 if (skeleton.skinText[where + 0] > color / 2) {
1289 skeleton.skinText[where + 0] = color / 2;
1291 skeleton.skinText[where + 1] = 0;
1292 skeleton.skinText[where + 2] = 0;
1293 } 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) {
1294 color = Random() % 85 + 170;
1295 where = i * skeleton.skinsize * 3 + j * 3;
1296 if (skeleton.skinText[where + 0] > color / 2) {
1297 skeleton.skinText[where + 0] = color / 2;
1299 skeleton.skinText[where + 1] = 0;
1300 skeleton.skinText[where + 2] = 0;
1305 if (creature == wolftype) {
1306 for (i = startx; i < endx; i++) {
1307 for (j = starty; j < endy; j++) {
1308 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) {
1309 color = Random() % 85 + 170;
1310 where = i * skeleton.skinsize * 3 + j * 3;
1311 if (skeleton.skinText[where + 0] > color / 2) {
1312 skeleton.skinText[where + 0] = color / 2;
1314 skeleton.skinText[where + 1] = 0;
1315 skeleton.skinText[where + 2] = 0;
1316 } else if (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) {
1317 color = Random() % 85 + 170;
1318 where = i * skeleton.skinsize * 3 + j * 3;
1319 if (skeleton.skinText[where + 0] > color / 2) {
1320 skeleton.skinText[where + 0] = color / 2;
1322 skeleton.skinText[where + 1] = 0;
1323 skeleton.skinText[where + 2] = 0;
1328 skeleton.drawmodel.textureptr.bind();
1331 bleedy = (1 + coordsy) * 512;
1332 bleedx = coordsx * 512;
1333 bleedy /= realtexdetail;
1334 bleedx /= realtexdetail;
1341 if (bleedx > skeleton.skinsize - 1) {
1342 bleedx = skeleton.skinsize - 1;
1344 if (bleedy > skeleton.skinsize - 1) {
1345 bleedy = skeleton.skinsize - 1;
1347 direction = abs(Random() % 2) * 2 - 1;
1349 if (whichtri == -1) {
1353 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1354 deathbleeding += bleeding;
1355 bloodloss += bleeding * 3;
1357 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1358 if (abs(Random() % 2) == 0) {
1359 aitype = gethelptype;
1362 aitype = attacktypecutoff;
1373 * guessing this performs a reversal
1375 void Person::Reverse()
1377 if (!((victim->aitype == playercontrolled || hostiletime > 1 || staggerdelay <= 0) && victim->animTarget != jumpupanim && victim->animTarget != jumpdownanim && (!Tutorial::active || cananger) && hostile)) {
1381 if (normaldotproduct(victim->facing, victim->coords - coords) > 0 && (victim->id != 0 || difficulty >= 2) && (creature != wolftype || victim->creature == wolftype)) {
1385 if (animTarget == sweepanim) {
1386 animTarget = sweepreversedanim;
1387 animCurrent = sweepreversedanim;
1388 victim->animCurrent = sweepreversalanim;
1389 victim->animTarget = sweepreversalanim;
1391 if (animTarget == spinkickanim) {
1392 animTarget = spinkickreversedanim;
1393 animCurrent = spinkickreversedanim;
1394 victim->animCurrent = spinkickreversalanim;
1395 victim->animTarget = spinkickreversalanim;
1397 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1398 if (animTarget == rabbittacklinganim) {
1401 victim->frameCurrent = 6;
1402 victim->frameTarget = 7;
1404 animTarget = upunchreversedanim;
1405 animCurrent = upunchreversedanim;
1406 victim->animCurrent = upunchreversalanim;
1407 victim->animTarget = upunchreversalanim;
1409 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1410 if (victim->weaponactive != -1) {
1411 victim->throwtogglekeydown = 1;
1412 XYZ tempVelocity = victim->velocity * .2;
1413 if (tempVelocity.x == 0) {
1414 tempVelocity.x = .1;
1416 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1417 victim->num_weapons--;
1418 if (victim->num_weapons) {
1419 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1420 if (victim->weaponstuck == victim->num_weapons) {
1421 victim->weaponstuck = 0;
1425 victim->weaponactive = -1;
1426 for (unsigned j = 0; j < Person::players.size(); j++) {
1427 Person::players[j]->wentforweapon = 0;
1431 animTarget = staffhitreversedanim;
1432 animCurrent = staffhitreversedanim;
1433 victim->animCurrent = staffhitreversalanim;
1434 victim->animTarget = staffhitreversalanim;
1436 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1437 if (victim->weaponactive != -1) {
1438 victim->throwtogglekeydown = 1;
1439 XYZ tempVelocity = victim->velocity * .2;
1440 if (tempVelocity.x == 0) {
1441 tempVelocity.x = .1;
1443 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1444 victim->num_weapons--;
1445 if (victim->num_weapons) {
1446 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1447 if (victim->weaponstuck == victim->num_weapons) {
1448 victim->weaponstuck = 0;
1452 victim->weaponactive = -1;
1453 for (unsigned j = 0; j < Person::players.size(); j++) {
1454 Person::players[j]->wentforweapon = 0;
1457 animTarget = staffspinhitreversedanim;
1458 animCurrent = staffspinhitreversedanim;
1459 victim->animCurrent = staffspinhitreversalanim;
1460 victim->animTarget = staffspinhitreversalanim;
1462 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1463 if (victim->weaponactive != -1) {
1464 victim->throwtogglekeydown = 1;
1465 XYZ tempVelocity = victim->velocity * .2;
1466 if (tempVelocity.x == 0) {
1467 tempVelocity.x = .1;
1469 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1470 victim->num_weapons--;
1471 if (victim->num_weapons) {
1472 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1473 if (victim->weaponstuck == victim->num_weapons) {
1474 victim->weaponstuck = 0;
1478 victim->weaponactive = -1;
1479 for (unsigned j = 0; j < Person::players.size(); j++) {
1480 Person::players[j]->wentforweapon = 0;
1483 animTarget = swordslashreversedanim;
1484 animCurrent = swordslashreversedanim;
1485 victim->animCurrent = swordslashreversalanim;
1486 victim->animTarget = swordslashreversalanim;
1488 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1489 if (victim->weaponactive != -1) {
1490 victim->throwtogglekeydown = 1;
1491 XYZ tempVelocity = victim->velocity * .2;
1492 if (tempVelocity.x == 0) {
1493 tempVelocity.x = .1;
1495 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1496 victim->num_weapons--;
1497 if (victim->num_weapons) {
1498 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1499 if (victim->weaponstuck == victim->num_weapons) {
1500 victim->weaponstuck = 0;
1504 victim->weaponactive = -1;
1505 for (unsigned j = 0; j < Person::players.size(); j++) {
1506 Person::players[j]->wentforweapon = 0;
1509 animTarget = knifeslashreversedanim;
1510 animCurrent = knifeslashreversedanim;
1511 victim->animCurrent = knifeslashreversalanim;
1512 victim->animTarget = knifeslashreversalanim;
1514 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1515 victim->targettilt2 = targettilt2;
1516 victim->frameCurrent = frameCurrent;
1517 victim->frameTarget = frameTarget;
1518 victim->target = target;
1519 victim->velocity = 0;
1520 victim->oldcoords = victim->coords;
1521 victim->coords = coords;
1522 victim->targetyaw = targetyaw;
1523 victim->yaw = targetyaw;
1524 victim->victim = this->shared_from_this();
1526 if (animTarget == winduppunchanim) {
1527 animTarget = winduppunchblockedanim;
1528 victim->animTarget = blockhighleftanim;
1529 victim->frameTarget = 1;
1530 victim->target = .5;
1531 victim->victim = this->shared_from_this();
1532 victim->targetyaw = targetyaw + 180;
1534 if (animTarget == wolfslapanim) {
1535 animTarget = winduppunchblockedanim;
1536 victim->animTarget = blockhighleftanim;
1537 victim->frameTarget = 1;
1538 victim->target = .5;
1539 victim->victim = this->shared_from_this();
1540 victim->targetyaw = targetyaw + 180;
1542 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1543 animTarget = swordslashparriedanim;
1544 parriedrecently = .4;
1545 victim->parriedrecently = 0;
1546 victim->animTarget = swordslashparryanim;
1547 victim->frameTarget = 1;
1548 victim->target = .5;
1549 victim->victim = this->shared_from_this();
1550 victim->targetyaw = targetyaw + 180;
1552 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1553 if (victim->weaponactive != -1) {
1554 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1555 if (weapons[victim->weaponids[0]].getType() == staff) {
1556 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1558 if (weapons[weaponids[0]].getType() == staff) {
1559 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1561 emit_sound_at(swordstaffsound, victim->coords);
1563 emit_sound_at(metalhitsound, victim->coords);
1567 victim->Puff(righthand);
1569 victim->frameTarget = 0;
1570 victim->animTarget = staggerbackhighanim;
1571 victim->targetyaw = targetyaw + 180;
1573 aim = DoRotation(facing, 0, 90, 0) * 21;
1575 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1576 victim->num_weapons--;
1577 if (victim->num_weapons) {
1578 victim->weaponids[0] = victim->weaponids[num_weapons];
1579 if (victim->weaponstuck == victim->num_weapons) {
1580 victim->weaponstuck = 0;
1583 victim->weaponactive = -1;
1584 for (unsigned i = 0; i < Person::players.size(); i++) {
1585 Person::players[i]->wentforweapon = 0;
1589 if (abs(Random() % 20) == 0) {
1590 if (weaponactive != -1) {
1591 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1592 if (weapons[victim->weaponids[0]].getType() == staff) {
1593 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1595 if (weapons[weaponids[0]].getType() == staff) {
1596 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1599 emit_sound_at(swordstaffsound, coords);
1601 emit_sound_at(metalhitsound, coords);
1609 animTarget = staggerbackhighanim;
1610 targetyaw = targetyaw + 180;
1612 aim = DoRotation(facing, 0, 90, 0) * 21;
1614 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1617 weaponids[0] = weaponids[num_weapons];
1618 if (weaponstuck == num_weapons) {
1623 for (unsigned i = 0; i < Person::players.size(); i++) {
1624 Person::players[i]->wentforweapon = 0;
1629 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1630 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1631 victim->animTarget = dodgebackanim;
1632 victim->frameTarget = 0;
1636 rotatetarget = coords - victim->coords;
1637 Normalise(&rotatetarget);
1638 victim->targetyaw = -asin(0 - rotatetarget.x);
1639 victim->targetyaw *= 360 / 6.28;
1640 if (rotatetarget.z < 0) {
1641 victim->targetyaw = 180 - victim->targetyaw;
1644 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1646 victim->lastattack3 = victim->lastattack2;
1647 victim->lastattack2 = victim->lastattack;
1648 victim->lastattack = victim->animTarget;
1650 victim->animTarget = sweepanim;
1651 victim->frameTarget = 0;
1655 rotatetarget = coords - victim->coords;
1656 Normalise(&rotatetarget);
1657 victim->targetyaw = -asin(0 - rotatetarget.x);
1658 victim->targetyaw *= 360 / 6.28;
1659 if (rotatetarget.z < 0) {
1660 victim->targetyaw = 180 - victim->targetyaw;
1663 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1665 victim->lastattack3 = victim->lastattack2;
1666 victim->lastattack2 = victim->lastattack;
1667 victim->lastattack = victim->animTarget;
1673 victim->velocity = 0;
1675 if (aitype != playercontrolled) {
1677 if (escapednum < 2) {
1678 int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
1679 if ((Random() % chances) == 0) {
1685 if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal) {
1693 void Person::DoDamage(float howmuch)
1697 damagetaken += howmuch / power;
1699 damagedealt += howmuch / power;
1703 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo)) {
1708 if (!Tutorial::active) {
1709 damage += howmuch / power;
1710 permanentdamage += howmuch / 2 / power;
1711 superpermanentdamage += howmuch / 4 / power;
1714 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2) {
1717 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt) {
1722 camerashake += howmuch / 100;
1723 if ((howmuch > 50 && damage > damagetolerance / 2)) {
1724 blackout = damage / damagetolerance;
1732 if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile)) {
1733 aitype = attacktypecutoff;
1735 if (!Tutorial::active && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1736 if (abs(Random() % 2) == 0) {
1737 aitype = gethelptype;
1740 aitype = attacktypecutoff;
1745 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1748 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1749 if (skeleton.free) {
1750 flatvelocity2 = skeleton.joints[i].velocity;
1751 flatfacing2 = skeleton.joints[i].position * scale + coords;
1753 flatvelocity2 = velocity;
1754 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1756 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1757 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1758 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1759 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1760 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1761 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1764 emit_sound_at(splattersound, coords);
1769 if (!dead && creature == wolftype) {
1770 award_bonus(0, Wolfbonus);
1777 if (!Tutorial::active || id == 0) {
1778 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1779 int whichsound = -1;
1781 if (creature == wolftype) {
1782 int i = abs(Random() % 2);
1784 whichsound = snarlsound;
1787 whichsound = snarl2sound;
1790 if (creature == rabbittype) {
1791 int i = abs(Random() % 2);
1793 whichsound = rabbitpainsound;
1795 if (i == 1 && damage > damagetolerance) {
1796 whichsound = rabbitpain1sound;
1800 if (whichsound != -1) {
1801 emit_sound_at(whichsound, coords);
1802 addEnvSound(coords);
1810 * calculate/animate head facing direction?
1812 void Person::DoHead()
1814 static XYZ rotatearound;
1816 static float lookspeed = 500;
1818 if (!freeze && !winfreeze) {
1821 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1822 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1824 while (targetheadyaw > 180) {
1825 targetheadyaw -= 360;
1827 while (targetheadyaw < -180) {
1828 targetheadyaw += 360;
1831 if (targetheadyaw > 160) {
1832 targetheadpitch = targetheadpitch * -1;
1834 if (targetheadyaw < -160) {
1835 targetheadpitch = targetheadpitch * -1;
1837 if (targetheadyaw > 160) {
1838 targetheadyaw = targetheadyaw - 180;
1840 if (targetheadyaw < -160) {
1841 targetheadyaw = targetheadyaw + 180;
1844 if (targetheadpitch > 120) {
1845 targetheadpitch = 120;
1847 if (targetheadpitch < -120) {
1848 targetheadpitch = -120;
1850 if (targetheadyaw > 120) {
1851 targetheadyaw = 120;
1853 if (targetheadyaw < -120) {
1854 targetheadyaw = -120;
1858 targetheadpitch = 0;
1861 if (targetheadyaw > 80) {
1864 if (targetheadyaw < -80) {
1865 targetheadyaw = -80;
1867 if (targetheadpitch > 50) {
1868 targetheadpitch = 50;
1870 if (targetheadpitch < -50) {
1871 targetheadpitch = -50;
1875 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed) {
1876 headyaw = targetheadyaw;
1877 } else if (headyaw > targetheadyaw) {
1878 headyaw -= multiplier * lookspeed;
1879 } else if (headyaw < targetheadyaw) {
1880 headyaw += multiplier * lookspeed;
1883 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2) {
1884 headpitch = targetheadpitch;
1885 } else if (headpitch > targetheadpitch) {
1886 headpitch -= multiplier * lookspeed / 2;
1887 } else if (headpitch < targetheadpitch) {
1888 headpitch += multiplier * lookspeed / 2;
1891 rotatearound = jointPos(neck);
1892 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1896 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1897 facing = DoRotation(facing, headpitch * .4, 0, 0);
1898 facing = DoRotation(facing, 0, headyaw * .4, 0);
1901 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1902 facing = DoRotation(facing, headpitch * .8, 0, 0);
1903 facing = DoRotation(facing, 0, headyaw * .8, 0);
1906 if (animTarget == walkanim) {
1907 facing = DoRotation(facing, headpitch * .6, 0, 0);
1908 facing = DoRotation(facing, 0, headyaw * .6, 0);
1911 skeleton.specialforward[0] = facing;
1912 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1913 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
1914 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1915 skeleton.FindRotationMuscle(i, animTarget);
1922 * ragdolls character?
1924 void Person::RagDoll(bool checkcollision)
1929 if (!skeleton.free) {
1933 if (id == 0 && isFlip()) {
1941 facing = DoRotation(facing, 0, yaw, 0);
1943 skeleton.freetime = 0;
1945 skeleton.longdead = 0;
1948 skeleton.broken = 0;
1949 skeleton.spinny = 1;
1951 skeleton.freefall = 1;
1953 if (!isnormal(velocity.x)) {
1956 if (!isnormal(velocity.y)) {
1959 if (!isnormal(velocity.z)) {
1962 if (!isnormal(yaw)) {
1965 if (!isnormal(coords.x)) {
1968 if (!isnormal(tilt)) {
1971 if (!isnormal(tilt2)) {
1975 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1976 skeleton.joints[i].delay = 0;
1977 skeleton.joints[i].locked = 0;
1978 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1979 if (!isnormal(skeleton.joints[i].position.x)) {
1980 skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1982 if (!isnormal(skeleton.joints[i].position.x)) {
1983 skeleton.joints[i].position = coords;
1985 skeleton.joints[i].position.y += .1;
1986 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1987 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1990 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1991 skeleton.joints[i].velocity = 0;
1992 skeleton.joints[i].velchange = 0;
1994 skeleton.DoConstraints(&coords, &scale);
1995 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
1996 skeleton.DoConstraints(&coords, &scale);
1997 skeleton.DoConstraints(&coords, &scale);
1998 skeleton.DoConstraints(&coords, &scale);
1999 skeleton.DoConstraints(&coords, &scale);
2002 speed = targetFrame().speed * 2;
2003 if (currentFrame().speed > targetFrame().speed) {
2004 speed = currentFrame().speed * 2;
2007 speed = transspeed * 2;
2012 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
2013 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height) {
2014 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);
2016 skeleton.joints[i].velocity = velocity / scale + facing * 5;
2018 change.x = (float)(Random() % 100) / 100;
2019 change.y = (float)(Random() % 100) / 100;
2020 change.z = (float)(Random() % 100) / 100;
2021 skeleton.joints[i].velocity += change;
2022 skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change;
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].velchange += change;
2028 skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change;
2031 if (checkcollision) {
2034 if (!skeleton.joints.empty()) {
2037 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
2038 average += skeleton.joints[j].position;
2040 average /= skeleton.joints.size();
2041 coords += average * scale;
2042 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
2043 skeleton.joints[j].position -= average;
2047 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
2048 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
2049 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
2050 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
2053 if (SphereCheck(&lowpoint, 3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
2054 coords.x = lowpoint.x;
2055 coords.z = lowpoint.z;
2064 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
2065 velocity += skeleton.joints[i].velocity * scale;
2067 velocity /= skeleton.joints.size();
2070 if (Random() % 2 == 0) {
2071 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
2072 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
2073 weapons[weaponids[0]].velocity.x += .01;
2076 weaponids[0] = weaponids[num_weapons];
2077 if (weaponstuck == num_weapons) {
2082 for (unsigned i = 0; i < Person::players.size(); i++) {
2083 Person::players[i]->wentforweapon = 0;
2088 animTarget = bounceidleanim;
2089 animCurrent = bounceidleanim;
2097 void Person::FootLand(bodypart whichfoot, float opacity)
2099 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
2100 cerr << "FootLand called on wrong bodypart" << endl;
2103 static XYZ terrainlight;
2104 static XYZ footvel, footpoint;
2105 if (opacity >= 1 || skiddelay <= 0) {
2108 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2109 if (distsq(&footpoint, &viewer)) {
2110 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
2112 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
2113 footvel = velocity / 5;
2114 if (footvel.y < .8) {
2117 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2118 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
2119 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
2120 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
2121 if (environment == snowyenvironment) {
2122 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
2124 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
2126 } else if (environment == grassyenvironment) {
2127 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
2128 } else if (environment == desertenvironment) {
2129 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
2131 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
2135 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
2136 footvel = velocity / 5;
2137 if (footvel.y < .8) {
2140 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2141 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
2142 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
2149 * make a puff effect at a body part (dust effect?)
2151 void Person::Puff(int whichlabel)
2153 static XYZ footvel, footpoint;
2156 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
2157 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
2161 * I think I added this in an attempt to clean up code
2163 void Person::setTargetAnimation(int animation)
2165 animTarget = animation;
2174 void Person::DoAnimations()
2176 if (!skeleton.free) {
2177 static float oldtarget;
2179 if (isIdle() && animCurrent != getIdle()) {
2180 normalsupdatedelay = 0;
2183 if (animTarget == tempanim || animCurrent == tempanim) {
2184 Animation::animations[tempanim] = tempanimation;
2186 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
2193 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
2194 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
2196 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z)) {
2199 if (!crouchkeydown && velocity.y >= -15) {
2203 if ((animCurrent == jumpupanim || animTarget == jumpdownanim) /*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
2208 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
2210 if (normaldotproduct(targfacing, velocity) >= -.3) {
2211 animTarget = flipanim;
2213 animTarget = backflipanim;
2215 crouchtogglekeydown = 1;
2224 if (Animation::animations[animTarget].attack != reversed) {
2227 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
2228 crouchtogglekeydown = 0;
2229 if (aitype == playercontrolled) {
2233 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain)) {
2237 crouchtogglekeydown = 1;
2241 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
2243 normalsupdatedelay = 0;
2248 if (animTarget == rollanim && frameTarget == 3 && onfire) {
2250 emit_sound_at(fireendsound, coords);
2251 pause_sound(stream_firesound);
2255 if (animTarget == rabbittacklinganim && frameTarget == 1) {
2256 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0) {
2259 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
2260 if (normaldotproduct(victim->facing, facing) > 0) {
2261 victim->animTarget = rabbittackledbackanim;
2263 victim->animTarget = rabbittackledfrontanim;
2265 victim->frameTarget = 2;
2268 victim->targetyaw = yaw;
2269 if (victim->aitype == gethelptype) {
2270 victim->DoDamage(victim->damagetolerance - victim->damage);
2272 //victim->DoDamage(30);
2273 if (creature == wolftype) {
2275 emit_sound_at(clawslicesound, victim->coords);
2277 victim->DoBloodBig(1 / victim->armorhead, 210);
2279 award_bonus(id, TackleBonus,
2280 victim->aitype == gethelptype ? 50 : 0);
2284 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2285 if (weapons[weaponids[0]].getType() == knife) {
2286 if (weaponactive == -1) {
2288 } else if (weaponactive == 0) {
2292 if (weaponactive == -1) {
2293 emit_sound_at(knifesheathesound, coords);
2295 if (weaponactive != -1) {
2296 emit_sound_at(knifedrawsound, coords, 128);
2299 drawtogglekeydown = 1;
2302 if (!Tutorial::active || id == 0) {
2303 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2304 int whichsound = -1;
2306 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2307 if (targetFrame().label == 1) {
2308 whichsound = footstepsound;
2310 whichsound = footstepsound2;
2312 if (targetFrame().label == 1) {
2313 FootLand(leftfoot, 1);
2315 if (targetFrame().label == 2) {
2316 FootLand(rightfoot, 1);
2318 if (targetFrame().label == 3 && isRun()) {
2319 FootLand(rightfoot, 1);
2320 FootLand(leftfoot, 1);
2323 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2324 if (targetFrame().label == 1) {
2325 whichsound = footstepsound3;
2327 whichsound = footstepsound4;
2332 if (targetFrame().label == 1) {
2333 whichsound = footstepsound3;
2335 whichsound = footstepsound4;
2338 if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2339 if (Animation::animations[animTarget].attack != neutral) {
2340 unsigned r = abs(Random() % 3);
2342 whichsound = lowwhooshsound;
2345 whichsound = midwhooshsound;
2348 whichsound = highwhooshsound;
2351 if (Animation::animations[animTarget].attack == neutral) {
2352 whichsound = movewhooshsound;
2354 } else if (targetFrame().label == 4) {
2355 whichsound = knifeswishsound;
2357 if (targetFrame().label == 8 && !Tutorial::active) {
2358 whichsound = landsound2;
2361 if (whichsound != -1) {
2362 emit_sound_at(whichsound, coords, 256.);
2365 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2366 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2367 addEnvSound(coords, 15);
2369 addEnvSound(coords, 6);
2374 if (targetFrame().label == 3) {
2376 emit_sound_at(whichsound, coords, 128.);
2383 if (!Tutorial::active || id == 0) {
2384 if (speechdelay <= 0) {
2385 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
2386 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2387 int whichsound = -1;
2388 if (targetFrame().label == 4 && aitype != playercontrolled) {
2389 if (Animation::animations[animTarget].attack != neutral) {
2390 unsigned r = abs(Random() % 4);
2391 if (creature == rabbittype) {
2393 whichsound = rabbitattacksound;
2396 whichsound = rabbitattack2sound;
2399 whichsound = rabbitattack3sound;
2402 whichsound = rabbitattack4sound;
2405 if (creature == wolftype) {
2407 whichsound = barksound;
2410 whichsound = bark2sound;
2413 whichsound = bark3sound;
2416 whichsound = barkgrowlsound;
2423 if (whichsound != -1) {
2424 emit_sound_at(whichsound, coords);
2431 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2432 FootLand(leftfoot, 1);
2433 FootLand(rightfoot, 1);
2437 currentoffset = targetoffset;
2438 frameTarget = frameCurrent;
2439 animCurrent = animTarget;
2442 if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2443 for (unsigned i = 0; i < weapons.size(); i++) {
2444 if (weapons[i].owner == -1) {
2445 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2446 if (distsq(&coords, &weapons[i].position) >= 1) {
2447 if (weapons[i].getType() != staff) {
2448 emit_sound_at(knifedrawsound, coords, 128.);
2458 if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2459 for (unsigned i = 0; i < weapons.size(); i++) {
2460 bool willwork = true;
2461 if (weapons[i].owner != -1) {
2462 if (Person::players[weapons[i].owner]->weaponstuck != -1) {
2463 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i)) {
2464 if (Person::players[weapons[i].owner]->num_weapons > 1) {
2470 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free)) {
2471 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2472 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2473 bool fleshstuck = false;
2474 if (weapons[i].owner != -1) {
2475 if (victim->weaponstuck != -1) {
2476 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2482 emit_sound_at(fleshstabremovesound, coords, 128.);
2484 if (weapons[i].getType() != staff) {
2485 emit_sound_at(knifedrawsound, coords, 128.);
2488 if (weapons[i].owner != -1) {
2489 victim = Person::players[weapons[i].owner];
2490 if (victim->num_weapons == 1) {
2491 victim->num_weapons = 0;
2493 victim->num_weapons = 1;
2496 //victim->weaponactive=-1;
2497 victim->skeleton.longdead = 0;
2498 victim->skeleton.free = 1;
2499 victim->skeleton.broken = 0;
2501 for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) {
2502 victim->skeleton.joints[j].velchange = 0;
2503 victim->skeleton.joints[j].locked = 0;
2509 Normalise(&relative);
2510 XYZ footvel, footpoint;
2512 footpoint = weapons[i].position;
2513 if (victim->weaponstuck != -1) {
2514 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2516 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2518 weapons[i].bloody = 2;
2519 weapons[i].blooddrip = 5;
2520 victim->weaponstuck = -1;
2523 if (victim->num_weapons > 0) {
2524 if (victim->weaponstuck != 0 && victim->weaponstuck != -1) {
2525 victim->weaponstuck = 0;
2527 if (victim->weaponids[0] == int(i)) {
2528 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2532 victim->jointVel(abdomen) += relative * 6;
2533 victim->jointVel(neck) += relative * 6;
2534 victim->jointVel(rightshoulder) += relative * 6;
2535 victim->jointVel(leftshoulder) += relative * 6;
2544 if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2545 if (weaponactive == -1) {
2547 } else if (weaponactive == 0) {
2549 if (num_weapons == 2) {
2551 buffer = weaponids[0];
2552 weaponids[0] = weaponids[1];
2553 weaponids[1] = buffer;
2556 if (weaponactive == -1) {
2557 emit_sound_at(knifesheathesound, coords, 128.);
2559 if (weaponactive != -1) {
2560 emit_sound_at(knifedrawsound, coords, 128.);
2564 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2565 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2566 Normalise(&rotatetarget);
2567 targetyaw = -asin(0 - rotatetarget.x);
2568 targetyaw *= 360 / 6.28;
2569 if (rotatetarget.z < 0) {
2570 targetyaw = 180 - targetyaw;
2573 if (animTarget == walljumprightkickanim) {
2576 if (animTarget == walljumpleftkickanim) {
2583 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0)) {
2587 if (distsq(&victim->coords, &/*Person::players[i]->*/ coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1) {
2595 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2596 animTarget = rabbittackleanim;
2598 emit_sound_at(jumpsound, coords);
2606 targetloc = velocity;
2607 Normalise(&targetloc);
2608 targetloc += coords;
2609 for (unsigned i = 0; i < Person::players.size(); i++) {
2611 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2612 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2617 if (closestid != -1) {
2618 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2620 victim = Person::players[closestid];
2621 coords = victim->coords;
2622 animCurrent = rabbittacklinganim;
2623 animTarget = rabbittacklinganim;
2627 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2628 rotatetarget = coords - victim->coords;
2629 Normalise(&rotatetarget);
2630 targetyaw = -asin(0 - rotatetarget.x);
2631 targetyaw *= 360 / 6.28;
2632 if (rotatetarget.z < 0) {
2633 targetyaw = 180 - targetyaw;
2636 if (animTarget != rabbitrunninganim) {
2637 emit_sound_at(jumpsound, coords, 128.);
2644 float damagemult = 1 * power;
2645 if (creature == wolftype) {
2646 damagemult = 2.5 * power;
2649 damagemult /= victim->damagetolerance / 200;
2651 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)) {
2652 if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2653 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2658 if (Random() % 2 || creature == wolftype) {
2661 if (creature == wolftype) {
2665 if (!Tutorial::active) {
2666 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2668 if (creature == wolftype) {
2669 emit_sound_at(clawslicesound, victim->coords, 128.);
2671 victim->DoBloodBig(2 / victim->armorhead, 175);
2675 relative = victim->coords - coords;
2677 Normalise(&relative);
2678 relative = DoRotation(relative, 0, -90, 0);
2679 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2680 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2682 victim->jointVel(head) += relative * damagemult * 200;
2684 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2690 if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2691 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2696 if (Random() % 2 || creature == wolftype) {
2698 if (creature == wolftype) {
2702 emit_sound_at(whooshhitsound, victim->coords);
2703 if (creature == wolftype) {
2704 emit_sound_at(clawslicesound, victim->coords, 128.);
2706 victim->DoBloodBig(2, 175);
2710 relative = victim->coords - coords;
2712 Normalise(&relative);
2714 Normalise(&relative);
2715 relative = DoRotation(relative, 0, 90, 0);
2716 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2717 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2719 victim->jointVel(head) += relative * damagemult * 100;
2721 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2725 if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2726 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2733 if (!Tutorial::active) {
2734 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2736 if (creature == wolftype) {
2737 emit_sound_at(clawslicesound, victim->coords, 128.);
2739 victim->DoBloodBig(2 / victim->armorhead, 175);
2745 Normalise(&relative);
2746 relative = DoRotation(relative, 0, -90, 0);
2747 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2748 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2750 victim->jointVel(head) += relative * damagemult * 200;
2752 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2754 if (victim->damage > victim->damagetolerance) {
2755 award_bonus(id, style);
2762 if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2763 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2770 if (!Tutorial::active) {
2771 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2773 if (creature == wolftype) {
2774 emit_sound_at(clawslicesound, victim->coords, 128.);
2776 victim->DoBloodBig(2 / victim->armorhead, 175);
2782 Normalise(&relative);
2783 relative = DoRotation(relative, 0, 90, 0);
2784 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2785 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2787 victim->jointVel(head) += relative * damagemult * 200;
2789 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2791 if (victim->damage > victim->damagetolerance) {
2792 award_bonus(id, style);
2799 if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2800 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2809 emit_sound_at(whooshhitsound, victim->coords);
2812 relative = victim->coords - coords;
2814 Normalise(&relative);
2815 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2816 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2818 victim->jointVel(head) += relative * damagemult * 100;
2820 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2824 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
2825 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2830 emit_sound_at(whooshhitsound, victim->coords, 128.);
2832 victim->skeleton.longdead = 0;
2833 victim->skeleton.free = 1;
2834 victim->skeleton.broken = 0;
2835 victim->skeleton.spinny = 1;
2837 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2838 victim->skeleton.joints[i].velchange = 0;
2839 victim->skeleton.joints[i].delay = 0;
2840 victim->skeleton.joints[i].locked = 0;
2841 //victim->skeleton.joints[i].velocity=0;
2847 Normalise(&relative);
2848 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2849 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2850 victim->skeleton.joints[i].position.y += relative.y * .3;
2851 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2852 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2854 victim->Puff(abdomen);
2855 victim->jointVel(abdomen).y = relative.y * 400;
2859 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2860 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2865 if (!Tutorial::active) {
2866 emit_sound_at(heavyimpactsound, coords, 128.);
2869 relative = victim->coords - coords;
2871 Normalise(&relative);
2872 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2873 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2875 victim->Puff(abdomen);
2876 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2880 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2881 victim->jointVel(abdomen) += relative * damagemult * 300;
2885 if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
2886 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2891 if (!Tutorial::active) {
2892 emit_sound_at(thudsound, coords);
2895 victim->skeleton.longdead = 0;
2896 victim->skeleton.free = 1;
2897 victim->skeleton.broken = 0;
2898 victim->skeleton.spinny = 1;
2900 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2901 victim->skeleton.joints[i].velchange = 0;
2902 //victim->skeleton.joints[i].delay=0;
2903 victim->skeleton.joints[i].locked = 0;
2906 relative = victim->coords - coords;
2907 Normalise(&relative);
2909 Normalise(&relative);
2910 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2911 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2913 if (!victim->dead) {
2917 victim->Puff(abdomen);
2918 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2919 victim->jointVel(abdomen) += relative * damagemult * 200;
2921 if (!victim->dead) {
2927 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2930 if (!victim->skeleton.free) {
2936 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2937 emit_sound_at(knifesheathesound, coords, 128.);
2940 if (victim && hasvictim) {
2941 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2943 XYZ where, startpoint, endpoint, movepoint, colpoint;
2944 float rotationpoint;
2946 if (weapons[weaponids[weaponactive]].getType() == knife) {
2947 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2948 where -= victim->coords;
2949 if (!victim->skeleton.free) {
2950 where = DoRotation(where, 0, -victim->yaw, 0);
2954 startpoint.y += 100;
2958 if (weapons[weaponids[weaponactive]].getType() == sword) {
2959 where = weapons[weaponids[weaponactive]].position;
2960 where -= victim->coords;
2961 if (!victim->skeleton.free) {
2962 where = DoRotation(where, 0, -victim->yaw, 0);
2965 where = weapons[weaponids[weaponactive]].tippoint;
2966 where -= victim->coords;
2967 if (!victim->skeleton.free) {
2968 where = DoRotation(where, 0, -victim->yaw, 0);
2972 if (weapons[weaponids[weaponactive]].getType() == staff) {
2973 where = weapons[weaponids[weaponactive]].position;
2974 where -= victim->coords;
2975 if (!victim->skeleton.free) {
2976 where = DoRotation(where, 0, -victim->yaw, 0);
2979 where = weapons[weaponids[weaponactive]].tippoint;
2980 where -= victim->coords;
2981 if (!victim->skeleton.free) {
2982 where = DoRotation(where, 0, -victim->yaw, 0);
2988 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2990 if (whichtri != -1) {
2991 if (victim->dead != 2) {
2992 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2993 if (!victim->dead) {
2994 award_bonus(id, FinishedBonus);
2998 weapons[weaponids[weaponactive]].bloody = 2;
3001 victim->skeleton.longdead = 0;
3002 victim->skeleton.free = 1;
3003 victim->skeleton.broken = 0;
3005 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3006 victim->skeleton.joints[i].velchange = 0;
3007 victim->skeleton.joints[i].locked = 0;
3008 //victim->skeleton.joints[i].velocity=0;
3010 emit_sound_at(fleshstabsound, coords, 128);
3012 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
3013 weapons[weaponids[weaponactive]].blooddrip += 5;
3014 weapons[weaponids[weaponactive]].blooddripdelay = 0;
3016 if (whichtri == -1) {
3018 emit_sound_at(knifesheathesound, coords, 128.);
3024 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3026 emit_sound_at(knifedrawsound, coords, 128);
3029 if (victim && hasvictim) {
3030 XYZ footvel, footpoint;
3032 emit_sound_at(fleshstabremovesound, coords, 128.);
3035 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
3037 if (weapons[weaponids[weaponactive]].getType() == sword) {
3038 XYZ where, startpoint, endpoint, movepoint;
3039 float rotationpoint;
3042 where = weapons[weaponids[weaponactive]].position;
3043 where -= victim->coords;
3044 if (!victim->skeleton.free) {
3045 where = DoRotation(where, 0, -victim->yaw, 0);
3048 where = weapons[weaponids[weaponactive]].tippoint;
3049 where -= victim->coords;
3050 if (!victim->skeleton.free) {
3051 where = DoRotation(where, 0, -victim->yaw, 0);
3057 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
3058 footpoint += victim->coords;
3060 if (whichtri == -1) {
3061 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
3064 if (weapons[weaponids[weaponactive]].getType() == staff) {
3065 XYZ where, startpoint, endpoint, movepoint;
3066 float rotationpoint;
3069 where = weapons[weaponids[weaponactive]].position;
3070 where -= victim->coords;
3071 if (!victim->skeleton.free) {
3072 where = DoRotation(where, 0, -victim->yaw, 0);
3075 where = weapons[weaponids[weaponactive]].tippoint;
3076 where -= victim->coords;
3077 if (!victim->skeleton.free) {
3078 where = DoRotation(where, 0, -victim->yaw, 0);
3084 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
3085 footpoint += victim->coords;
3087 if (whichtri == -1) {
3088 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
3091 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
3093 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
3094 victim->skeleton.longdead = 0;
3095 victim->skeleton.free = 1;
3096 victim->skeleton.broken = 0;
3098 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3099 victim->skeleton.joints[i].velchange = 0;
3100 victim->skeleton.joints[i].locked = 0;
3101 //victim->skeleton.joints[i].velocity=0;
3107 Normalise(&relative);
3108 //victim->Puff(abdomen);
3110 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
3113 if (victim->bloodloss < victim->damagetolerance) {
3114 victim->bloodloss += 1000;
3118 victim->jointVel(abdomen) += relative * damagemult * 20;
3122 if (!hasvictim && onterrain) {
3123 weapons[weaponids[weaponactive]].bloody = 0;
3124 weapons[weaponids[weaponactive]].blooddrip = 0;
3128 if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3129 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
3138 if (!Tutorial::active) {
3139 emit_sound_at(heavyimpactsound, victim->coords, 128);
3144 relative = victim->coords - coords;
3146 Normalise(&relative);
3147 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3148 victim->skeleton.joints[i].velocity = relative * 30;
3150 victim->jointVel(head) += relative * damagemult * 150;
3152 victim->frameTarget = 0;
3153 victim->animTarget = staggerbackhardanim;
3154 victim->targetyaw = targetyaw + 180;
3156 victim->stunned = 1;
3159 victim->Puff(abdomen);
3160 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
3166 if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3167 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
3172 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
3173 if (!Tutorial::active) {
3174 emit_sound_at(thudsound, victim->coords);
3176 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
3177 if (!Tutorial::active) {
3178 emit_sound_at(whooshhitsound, victim->coords);
3181 if (!Tutorial::active) {
3182 emit_sound_at(heavyimpactsound, victim->coords);
3186 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight) {
3190 relative = victim->coords - coords;
3192 Normalise(&relative);
3194 Normalise(&relative);
3195 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3196 victim->skeleton.joints[i].velocity = relative * 5;
3198 victim->jointVel(abdomen) += relative * damagemult * 400;
3200 victim->frameTarget = 0;
3201 victim->animTarget = staggerbackhardanim;
3202 victim->targetyaw = targetyaw + 180;
3204 victim->stunned = 1;
3206 victim->Puff(abdomen);
3207 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
3213 if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3214 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3215 if (victim->id == 0) {
3218 emit_sound_at(landsound2, victim->coords);
3224 if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3225 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3226 if (victim->id == 0) {
3230 if (weaponactive != -1) {
3231 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3232 if (weapons[victim->weaponids[0]].getType() == staff) {
3233 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3235 if (weapons[weaponids[0]].getType() == staff) {
3236 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3239 emit_sound_at(swordstaffsound, victim->coords);
3241 emit_sound_at(metalhitsound, victim->coords);
3249 if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3250 if (weaponactive != -1) {
3253 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);
3255 weapons[weaponids[0]].thrown(aim * 50);
3258 weaponids[0] = weaponids[num_weapons];
3264 if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3266 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 && /*Animation::animations[victim->animTarget].height!=lowheight&&*/ victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
3268 if (!Tutorial::active) {
3269 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
3272 award_bonus(id, Slicebonus);
3273 if (!Tutorial::active) {
3274 emit_sound_at(knifeslicesound, victim->coords);
3276 //victim->jointVel(abdomen)+=relative*damagemult*200;
3277 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
3278 if (victim->id != 0 || difficulty == 2) {
3279 victim->frameTarget = 0;
3280 victim->animTarget = staggerbackhardanim;
3281 victim->targetyaw = targetyaw + 180;
3285 victim->lowreversaldelay = 0;
3286 victim->highreversaldelay = 0;
3287 if (aitype != playercontrolled) {
3288 weaponmissdelay = .6;
3291 if (!Tutorial::active) {
3292 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3293 weapons[weaponids[weaponactive]].bloody = 1;
3295 weapons[weaponids[weaponactive]].blooddrip += 3;
3298 XYZ footvel, footpoint;
3300 if (skeleton.free) {
3301 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3303 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3305 if (Tutorial::active) {
3306 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
3309 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
3311 footvel = DoRotation(facing, 0, 90, 0) * .8;
3312 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3313 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3314 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3315 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3317 victim->DoDamage(damagemult * 0);
3321 if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3322 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
3323 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
3324 award_bonus(id, Slashbonus);
3326 if (!Tutorial::active) {
3327 if (normaldotproduct(victim->facing, victim->coords - coords) < 0) {
3328 victim->DoBloodBig(2 / victim->armorhigh, 190);
3330 victim->DoBloodBig(2 / victim->armorhigh, 185);
3332 victim->deathbleeding = 1;
3333 emit_sound_at(swordslicesound, victim->coords);
3334 victim->frameTarget = 0;
3335 victim->animTarget = staggerbackhardanim;
3336 victim->targetyaw = targetyaw + 180;
3338 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3339 weapons[weaponids[weaponactive]].bloody = 1;
3341 weapons[weaponids[weaponactive]].blooddrip += 3;
3343 float bloodlossamount;
3344 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
3345 victim->bloodloss += bloodlossamount / victim->armorhigh;
3346 victim->DoDamage(damagemult * 0);
3348 XYZ footvel, footpoint;
3350 if (skeleton.free) {
3351 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3353 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3356 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3358 footvel = DoRotation(facing, 0, 90, 0) * .8;
3360 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3361 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3362 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3363 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3366 if (victim->weaponactive != -1) {
3367 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3368 if (weapons[victim->weaponids[0]].getType() == staff) {
3369 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3371 if (weapons[weaponids[0]].getType() == staff) {
3372 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3375 emit_sound_at(swordstaffsound, victim->coords);
3377 emit_sound_at(metalhitsound, victim->coords);
3382 victim->Puff(righthand);
3384 victim->frameTarget = 0;
3385 victim->animTarget = staggerbackhighanim;
3386 victim->targetyaw = targetyaw + 180;
3388 aim = DoRotation(facing, 0, 90, 0) * 21;
3390 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3391 victim->num_weapons--;
3392 if (victim->num_weapons) {
3393 victim->weaponids[0] = victim->weaponids[num_weapons];
3394 if (victim->weaponstuck == victim->num_weapons) {
3395 victim->weaponstuck = 0;
3398 victim->weaponactive = -1;
3399 for (unsigned i = 0; i < Person::players.size(); i++) {
3400 Person::players[i]->wentforweapon = 0;
3406 if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3407 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3408 if (!Tutorial::active) {
3409 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3414 if (Random() % 2 || creature == wolftype) {
3417 emit_sound_at(staffheadsound, victim->coords);
3421 relative = victim->coords - coords;
3423 Normalise(&relative);
3424 relative = DoRotation(relative, 0, 90, 0);
3426 Normalise(&relative);
3427 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3428 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3430 victim->jointVel(head) += relative * damagemult * 230;
3431 victim->jointVel(neck) += relative * damagemult * 230;
3433 if (!Tutorial::active) {
3434 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3436 award_bonus(id, solidhit, 30);
3441 if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3442 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3443 if (!Tutorial::active) {
3444 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3449 if (Random() % 2 || creature == wolftype) {
3452 emit_sound_at(staffheadsound, victim->coords);
3456 relative = victim->coords - coords;
3458 Normalise(&relative);
3459 relative = DoRotation(relative, 0, -90, 0);
3460 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3461 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3463 victim->jointVel(head) += relative * damagemult * 220;
3464 victim->jointVel(neck) += relative * damagemult * 220;
3466 if (!Tutorial::active) {
3467 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3469 award_bonus(id, solidhit, 60);
3474 if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3475 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3477 if (!Tutorial::active) {
3478 if (!victim->dead) {
3479 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3484 if (Random() % 2 || creature == wolftype) {
3487 emit_sound_at(staffbodysound, victim->coords);
3489 victim->skeleton.longdead = 0;
3490 victim->skeleton.free = 1;
3491 victim->skeleton.broken = 0;
3493 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3494 victim->skeleton.joints[i].velchange = 0;
3495 victim->skeleton.joints[i].locked = 0;
3496 //victim->skeleton.joints[i].velocity=0;
3503 Normalise(&relative);
3504 if (!victim->dead) {
3505 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3506 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3508 victim->jointVel(abdomen) += relative * damagemult * 40;
3511 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3512 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3515 victim->Puff(abdomen);
3516 if (!Tutorial::active) {
3517 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3519 if (!victim->dead) {
3520 award_bonus(id, solidhit, 40);
3526 if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3527 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3533 relative = victim->coords - coords;
3535 Normalise(&relative);
3539 if (Animation::animations[victim->animTarget].height == lowheight) {
3545 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3546 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3548 victim->jointVel(head) += relative * damagemult * 200;
3549 if (!Tutorial::active) {
3550 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3553 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3554 if (victim->howactive == typesleeping) {
3555 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3557 if (creature == wolftype) {
3558 emit_sound_at(clawslicesound, victim->coords, 128.);
3560 victim->DoBloodBig(2 / victim->armorhead, 175);
3563 if (victim->damage >= victim->damagetolerance) {
3566 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3567 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3569 victim->jointVel(abdomen) += relative * damagemult * 200;
3570 victim->frameTarget = 0;
3571 victim->animTarget = staggerbackhighanim;
3572 victim->targetyaw = targetyaw + 180;
3574 if (!Tutorial::active) {
3575 emit_sound_at(landsound2, victim->coords, 128.);
3577 victim->Puff(abdomen);
3578 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3579 if (creature == wolftype) {
3580 emit_sound_at(clawslicesound, victim->coords, 128.);
3582 victim->DoBloodBig(2 / victim->armorhigh, 170);
3588 if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3589 if ((victim->animTarget != jumpupanim) &&
3590 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3591 (victim != this->shared_from_this())) {
3596 if (!Tutorial::active) {
3597 emit_sound_at(landsound2, victim->coords, 128.);
3600 relative = victim->coords - coords;
3602 Normalise(&relative);
3604 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3607 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3608 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3610 relative = DoRotation(relative, 0, -90, 0);
3612 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3613 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) {
3614 victim->skeleton.joints[i].velocity = relative * 80;
3617 victim->Puff(rightankle);
3618 victim->Puff(leftankle);
3619 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3621 if (victim->damage >= victim->damagetolerance) {
3624 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3625 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3627 relative = DoRotation(relative, 0, -90, 0);
3628 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3629 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) {
3630 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3633 victim->jointVel(abdomen) += relative * damagemult * 200;
3634 victim->frameTarget = 0;
3635 victim->animTarget = staggerbackhighanim;
3636 victim->targetyaw = targetyaw + 180;
3638 if (!Tutorial::active) {
3639 emit_sound_at(landsound2, victim->coords, 128.);
3641 victim->Puff(abdomen);
3642 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3649 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3650 if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3659 if (!Tutorial::active) {
3660 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3662 if (creature == wolftype) {
3663 emit_sound_at(clawslicesound, victim->coords, 128);
3665 victim->DoBloodBig(2 / victim->armorhigh, 170);
3669 relative = victim->coords - oldcoords;
3671 Normalise(&relative);
3672 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3673 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3675 victim->jointVel(abdomen) += relative * damagemult * 200;
3676 victim->Puff(abdomen);
3677 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3679 award_bonus(id, Reversal);
3682 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3683 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3684 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3685 takeWeapon(victim->weaponids[victim->weaponactive]);
3686 victim->num_weapons--;
3687 if (victim->num_weapons > 0) {
3688 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3690 victim->weaponactive = -1;
3695 if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3704 emit_sound_at(whooshhitsound, victim->coords, 128.);
3707 relative = victim->coords - oldcoords;
3709 Normalise(&relative);
3710 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3711 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3713 victim->jointVel(abdomen) += relative * damagemult * 200;
3715 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3718 if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3728 award_bonus(id, staffreversebonus);
3730 if (!Tutorial::active) {
3731 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3734 award_bonus(id, staffreversebonus); // Huh, again?
3737 relative = victim->coords - oldcoords;
3739 Normalise(&relative);
3740 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3741 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3743 victim->jointVel(abdomen) += relative * damagemult * 200;
3745 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3748 if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3754 Normalise(&relative);
3756 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3757 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3759 victim->jointVel(lefthand) *= .1;
3760 victim->jointVel(leftwrist) *= .2;
3761 victim->jointVel(leftelbow) *= .5;
3762 victim->jointVel(leftshoulder) *= .7;
3763 victim->jointVel(righthand) *= .1;
3764 victim->jointVel(rightwrist) *= .2;
3765 victim->jointVel(rightelbow) *= .5;
3766 victim->jointVel(rightshoulder) *= .7;
3768 victim->Puff(abdomen);
3769 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3771 award_bonus(id, Reversal);
3775 if (weaponactive != -1 || creature == wolftype) {
3778 if (creature == rabbittype && weaponactive != -1) {
3779 if (weapons[weaponids[0]].getType() == staff) {
3784 if (weaponactive != -1) {
3785 victim->DoBloodBig(2 / victim->armorhigh, 225);
3786 emit_sound_at(knifeslicesound, victim->coords);
3787 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3788 weapons[weaponids[weaponactive]].bloody = 1;
3790 weapons[weaponids[weaponactive]].blooddrip += 3;
3792 if (weaponactive == -1 && creature == wolftype) {
3793 emit_sound_at(clawslicesound, victim->coords, 128.);
3795 victim->DoBloodBig(2 / victim->armorhigh, 175);
3800 if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3806 Normalise(&relative);
3808 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3809 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3811 victim->jointVel(lefthand) *= .1 - 1;
3812 victim->jointVel(leftwrist) *= .2 - 1;
3813 victim->jointVel(leftelbow) *= .5 - 1;
3814 victim->jointVel(leftshoulder) *= .7 - 1;
3815 victim->jointVel(righthand) *= .1 - 1;
3816 victim->jointVel(rightwrist) *= .2 - 1;
3817 victim->jointVel(rightelbow) *= .5 - 1;
3818 victim->jointVel(rightshoulder) *= .7 - 1;
3820 award_bonus(id, swordreversebonus);
3823 if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3832 if (!Tutorial::active) {
3833 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3837 relative = victim->coords - oldcoords;
3839 Normalise(&relative);
3840 relative = DoRotation(relative, 0, -90, 0);
3841 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3842 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3844 victim->jointVel(abdomen) += relative * damagemult * 200;
3845 victim->Puff(abdomen);
3846 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3848 award_bonus(id, Reversal);
3851 if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3854 victim->skeleton.spinny = 0;
3856 relative = facing * -1;
3858 Normalise(&relative);
3859 if (victim->id == 0) {
3862 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3863 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3865 victim->damage = victim->damagetolerance;
3866 victim->permanentdamage = victim->damagetolerance - 1;
3869 if (weaponactive != -1 || creature == wolftype) {
3872 if (creature == rabbittype && weaponactive != -1) {
3873 if (weapons[weaponids[0]].getType() == staff) {
3878 if (weaponactive != -1) {
3879 victim->DoBloodBig(200, 225);
3880 emit_sound_at(knifeslicesound, victim->coords);
3882 weapons[weaponids[weaponactive]].bloody = 2;
3884 weapons[weaponids[weaponactive]].blooddrip += 5;
3887 if (creature == wolftype && weaponactive == -1) {
3888 emit_sound_at(clawslicesound, victim->coords, 128.);
3890 victim->DoBloodBig(2, 175);
3893 award_bonus(id, spinecrusher);
3896 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3897 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3899 if (animTarget == knifefollowanim) {
3900 victim->DoBloodBig(200, 210);
3902 if (animTarget == knifesneakattackanim) {
3903 XYZ footvel, footpoint;
3905 footpoint = weapons[weaponids[0]].tippoint;
3907 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3909 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3910 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3911 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3912 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3913 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3914 victim->DoBloodBig(200, 195);
3915 award_bonus(id, tracheotomy);
3917 if (animTarget == knifefollowanim) {
3918 award_bonus(id, Stabbonus);
3919 XYZ footvel, footpoint;
3921 footpoint = weapons[weaponids[0]].tippoint;
3923 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3925 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3926 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3927 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3928 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3929 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3931 victim->bloodloss += 10000;
3932 victim->velocity = 0;
3933 emit_sound_at(fleshstabsound, victim->coords);
3935 weapons[weaponids[weaponactive]].bloody = 2;
3937 weapons[weaponids[weaponactive]].blooddrip += 5;
3941 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3943 victim->velocity = 0;
3944 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3945 victim->skeleton.joints[i].velocity = 0;
3947 if (animTarget == knifefollowanim) {
3949 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3950 victim->skeleton.joints[i].velocity = 0;
3953 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3954 emit_sound_at(fleshstabremovesound, victim->coords);
3956 weapons[weaponids[weaponactive]].bloody = 2;
3958 weapons[weaponids[weaponactive]].blooddrip += 5;
3960 XYZ footvel, footpoint;
3962 footpoint = weapons[weaponids[0]].tippoint;
3964 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3966 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3967 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3968 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3969 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3970 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3974 if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3975 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3976 award_bonus(id, backstab);
3980 XYZ footvel, footpoint;
3982 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3984 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3986 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3987 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3988 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3989 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3990 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3991 victim->DoBloodBig(200, 180);
3992 victim->DoBloodBig(200, 215);
3993 victim->bloodloss += 10000;
3994 victim->velocity = 0;
3995 emit_sound_at(fleshstabsound, victim->coords);
3997 weapons[weaponids[weaponactive]].bloody = 2;
3999 weapons[weaponids[weaponactive]].blooddrip += 5;
4003 if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
4005 victim->velocity = 0;
4006 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
4007 victim->skeleton.joints[i].velocity = 0;
4009 if (weaponactive != -1) {
4010 emit_sound_at(fleshstabremovesound, victim->coords);
4012 weapons[weaponids[weaponactive]].bloody = 2;
4014 weapons[weaponids[weaponactive]].blooddrip += 5;
4016 XYZ footvel, footpoint;
4018 footpoint = weapons[weaponids[0]].tippoint;
4020 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
4022 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
4023 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
4024 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
4025 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
4026 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
4030 if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
4039 if (weaponactive == -1) {
4040 if (!Tutorial::active) {
4041 emit_sound_at(heavyimpactsound, victim->coords, 128.);
4046 if (weaponactive != -1 || creature == wolftype) {
4049 if (creature == rabbittype && weaponactive != -1) {
4050 if (weapons[weaponids[0]].getType() == staff) {
4055 if (weaponactive != -1) {
4056 victim->DoBloodBig(2 / victim->armorhead, 225);
4057 emit_sound_at(knifeslicesound, victim->coords);
4058 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
4059 weapons[weaponids[weaponactive]].bloody = 1;
4061 weapons[weaponids[weaponactive]].blooddrip += 3;
4063 if (weaponactive == -1 && creature == wolftype) {
4064 emit_sound_at(clawslicesound, victim->coords, 128.);
4066 victim->DoBloodBig(2 / victim->armorhead, 175);
4070 award_bonus(id, Reversal);
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;
4085 if (victim->damage < victim->damagetolerance - 100) {
4086 victim->velocity = relative * 200;
4088 victim->DoDamage(damagemult * 100 / victim->protectionhead);
4089 victim->velocity = 0;
4092 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))) {
4096 relative = facing * -1;
4098 Normalise(&relative);
4099 relative = DoRotation(relative, 0, 90, 0);
4101 Normalise(&relative);
4102 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
4103 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
4105 victim->jointVel(head) += relative * damagemult * 200;
4108 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim)) {
4109 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
4110 award_bonus(id, reverseko);
4116 if (frameTarget > int(Animation::animations[animCurrent].frames.size()) - 1) {
4119 animTarget = getIdle();
4120 FootLand(leftfoot, 1);
4121 FootLand(rightfoot, 1);
4123 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
4124 animTarget = rollanim;
4126 emit_sound_at(movewhooshsound, coords, 128.);
4128 if (animCurrent == staggerbackhighanim) {
4129 animTarget = getIdle();
4131 if (animCurrent == staggerbackhardanim) {
4132 animTarget = getIdle();
4134 if (animCurrent == removeknifeanim) {
4135 animTarget = getIdle();
4137 if (animCurrent == crouchremoveknifeanim) {
4138 animTarget = getCrouch();
4140 if (animCurrent == backhandspringanim) {
4141 animTarget = getIdle();
4143 if (animCurrent == dodgebackanim) {
4144 animTarget = getIdle();
4146 if (animCurrent == drawleftanim) {
4147 animTarget = getIdle();
4149 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
4150 animTarget = getIdle();
4151 if (animCurrent == crouchdrawrightanim) {
4152 animTarget = getCrouch();
4154 if (weaponactive == -1) {
4156 } else if (weaponactive == 0) {
4158 if (num_weapons == 2) {
4160 buffer = weaponids[0];
4161 weaponids[0] = weaponids[1];
4162 weaponids[1] = buffer;
4166 if (weaponactive == -1) {
4167 emit_sound_at(knifesheathesound, coords, 128.);
4169 if (weaponactive != -1) {
4170 emit_sound_at(knifedrawsound, coords, 128.);
4173 if (animCurrent == rollanim) {
4174 animTarget = getCrouch();
4175 FootLand(leftfoot, 1);
4176 FootLand(rightfoot, 1);
4179 if (animTarget == walljumprightkickanim) {
4182 if (animTarget == walljumpleftkickanim) {
4185 animTarget = jumpdownanim;
4187 if (animCurrent == climbanim) {
4188 animTarget = getCrouch();
4190 coords += facing * .1;
4191 if (!isnormal(coords.x)) {
4202 if (animTarget == rabbitkickreversalanim) {
4203 animTarget = getCrouch();
4206 if (animTarget == jumpreversalanim) {
4207 animTarget = getCrouch();
4210 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
4211 if (attackkeydown && animTarget != walljumpfrontanim) {
4213 float closestdist = -1;
4215 if (Person::players.size() > 1) {
4216 for (unsigned i = 0; i < Person::players.size(); i++) {
4217 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4218 distance = distsq(&Person::players[i]->coords, &coords);
4219 if (closestdist == -1 || distance < closestdist) {
4220 closestdist = distance;
4226 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4227 victim = Person::players[closest];
4228 animTarget = walljumprightkickanim;
4230 XYZ rotatetarget = victim->coords - coords;
4231 Normalise(&rotatetarget);
4232 yaw = -asin(0 - rotatetarget.x);
4234 if (rotatetarget.z < 0) {
4237 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4238 velocity = (victim->coords - coords) * 4;
4243 if (animTarget == walljumpbackanim) {
4244 animTarget = backflipanim;
4246 velocity = facing * -8;
4249 resume_stream(whooshsound);
4252 if (animTarget == walljumprightanim) {
4253 animTarget = rightflipanim;
4257 velocity = DoRotation(facing, 0, 30, 0) * -8;
4260 if (animTarget == walljumpfrontanim) {
4261 animTarget = frontflipanim;
4265 velocity = facing * 8;
4269 resume_stream(whooshsound);
4272 if (animTarget == walljumpleftanim) {
4273 if (attackkeydown) {
4275 float closestdist = -1;
4277 if (Person::players.size() > 1) {
4278 for (unsigned i = 0; i < Person::players.size(); i++) {
4279 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4280 distance = distsq(&Person::players[i]->coords, &coords);
4281 if (closestdist == -1 || distance < closestdist) {
4282 closestdist = distance;
4288 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4289 victim = Person::players[closest];
4290 animTarget = walljumpleftkickanim;
4292 XYZ rotatetarget = victim->coords - coords;
4293 Normalise(&rotatetarget);
4294 yaw = -asin(0 - rotatetarget.x);
4296 if (rotatetarget.z < 0) {
4299 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4300 velocity = (victim->coords - coords) * 4;
4305 if (animTarget != walljumpleftkickanim) {
4306 animTarget = leftflipanim;
4310 velocity = DoRotation(facing, 0, -30, 0) * -8;
4314 resume_stream(whooshsound);
4317 if (animTarget == sneakattackanim) {
4318 animCurrent = getCrouch();
4319 animTarget = getCrouch();
4326 transspeed = 1000000;
4327 targetheadyaw += 180;
4328 coords -= facing * .7;
4330 coords.y = terrain.getHeight(coords.x, coords.z);
4335 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
4336 animTarget = getIdle();
4339 coords.y = terrain.getHeight(coords.x, coords.z);
4344 if (animCurrent == knifefollowanim) {
4345 animTarget = getIdle();
4348 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
4349 float ycoords = oldcoords.y;
4350 animTarget = getStop();
4355 transspeed = 1000000;
4356 targetheadyaw += 180;
4357 if (!isnormal(coords.x)) {
4360 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim) {
4361 oldcoords = coords + facing * .5;
4362 } else if (animCurrent == sweepreversalanim) {
4363 oldcoords = coords + facing * 1.1;
4364 } else if (animCurrent == upunchreversalanim) {
4365 oldcoords = coords + facing * 1.5;
4368 targetheadyaw += 180;
4371 } else if (animCurrent == knifeslashreversalanim) {
4372 oldcoords = coords + facing * .5;
4375 targetheadyaw += 90;
4378 } else if (animCurrent == staffspinhitreversalanim) {
4381 targetheadyaw += 180;
4386 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
4388 oldcoords.y = ycoords;
4390 currentoffset = coords - oldcoords;
4396 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4401 if (Animation::animations[animTarget].attack == reversed) {
4403 if (animTarget == sweepreversedanim) {
4406 animTarget = backhandspringanim;
4408 emit_sound_at(landsound, coords, 128);
4410 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4411 animTarget = rollanim;
4414 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4415 coords.y = oldcoords.y;
4417 if (animCurrent == knifeslashreversedanim) {
4418 animTarget = rollanim;
4423 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4424 coords.y = oldcoords.y;
4428 animTarget = jumpdownanim;
4431 animTarget = getIdle();
4433 if (wasLandhard()) {
4434 animTarget = getIdle();
4436 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4437 animTarget = getIdle();
4439 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4440 coords.y = oldcoords.y;
4441 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4442 targetoffset.y = coords.y;
4444 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4446 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4447 currentoffset.y -= (coords.y - targetoffset.y);
4448 coords.y = targetoffset.y;
4450 normalsupdatedelay = 0;
4452 if (animCurrent == upunchanim) {
4453 animTarget = getStop();
4454 normalsupdatedelay = 0;
4457 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4461 if (num_weapons > 0) {
4462 if (weapons[0].getType() == staff) {
4471 rabbitkickragdoll = 1;
4473 if (animCurrent == rabbitkickreversedanim) {
4479 skeleton.spinny = 0;
4480 SolidHitBonus(!id); // FIXME: tricky id
4484 animTarget = rollanim;
4487 pause_sound(whooshsound);
4492 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4496 skeleton.spinny = 0;
4498 if (animCurrent == jumpreversedanim) {
4504 skeleton.spinny = 0;
4505 SolidHitBonus(!id); // FIXME: tricky id
4509 animTarget = rollanim;
4510 coords += facing * 2;
4512 pause_sound(whooshsound);
4518 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) {
4519 animTarget = getupfromfrontanim;
4521 } else if (Animation::animations[animCurrent].attack == normalattack) {
4522 animTarget = getIdle();
4525 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4526 animTarget = blockhighleftstrikeanim;
4528 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4529 animTarget = getIdle();
4532 if (animCurrent == spinkickanim && victim->skeleton.free) {
4533 if (creature == rabbittype) {
4534 animTarget = fightidleanim;
4540 if (isIdle() && !wasIdle()) {
4541 normalsupdatedelay = 0;
4544 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4545 animTarget = jumpdownanim;
4548 if (!skeleton.free) {
4550 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4551 if (!isRun() || !wasRun()) {
4552 if (targetFrame().speed > currentFrame().speed) {
4553 target += multiplier * targetFrame().speed * speed * 2;
4555 if (targetFrame().speed <= currentFrame().speed) {
4556 target += multiplier * currentFrame().speed * speed * 2;
4559 if (isRun() && wasRun()) {
4561 tempspeed = velspeed;
4562 if (tempspeed < 10 * speedmult) {
4563 tempspeed = 10 * speedmult;
4565 /* FIXME - mixed of target and current here, is that intended? */
4566 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4568 } else if (transspeed) {
4569 target += multiplier * transspeed * speed * 2;
4571 if (!isRun() || !wasRun()) {
4572 if (targetFrame().speed > currentFrame().speed) {
4573 target += multiplier * targetFrame().speed * 2;
4575 if (targetFrame().speed <= currentFrame().speed) {
4576 target += multiplier * currentFrame().speed * 2;
4581 if (animCurrent != animTarget) {
4582 target = (target + oldtarget) / 2;
4586 frameCurrent = frameTarget;
4590 rot = targetrot * target;
4591 yaw += rot - oldrot;
4597 if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
4598 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4600 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4602 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4603 skeleton.joints[i].position = currentFrame().joints[i].position;
4606 skeleton.FindForwards();
4608 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4609 if (skeleton.muscles[i].visible) {
4610 skeleton.FindRotationMuscle(i, animTarget);
4613 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4614 if (skeleton.muscles[i].visible) {
4615 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4616 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4618 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4619 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4621 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4622 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4628 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4629 skeleton.joints[i].position = targetFrame().joints[i].position;
4632 skeleton.FindForwards();
4634 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4635 if (skeleton.muscles[i].visible) {
4636 skeleton.FindRotationMuscle(i, animTarget);
4639 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4640 if (skeleton.muscles[i].visible) {
4641 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4642 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4644 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4645 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4647 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4648 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4650 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) {
4651 skeleton.muscles[i].newrotate3 -= 360;
4653 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) {
4654 skeleton.muscles[i].newrotate3 += 360;
4656 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) {
4657 skeleton.muscles[i].newrotate2 -= 360;
4659 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) {
4660 skeleton.muscles[i].newrotate2 += 360;
4662 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) {
4663 skeleton.muscles[i].newrotate1 -= 360;
4665 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) {
4666 skeleton.muscles[i].newrotate1 += 360;
4672 oldanimCurrent = animCurrent;
4673 oldanimTarget = animTarget;
4674 oldframeTarget = frameTarget;
4675 oldframeCurrent = frameCurrent;
4677 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4678 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target - skeleton.joints[i].position) / multiplier;
4679 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target;
4681 offset = currentoffset * (1 - target) + targetoffset * target;
4682 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4683 if (skeleton.muscles[i].visible) {
4684 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * target;
4685 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * target;
4686 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * target;
4691 if (isLanding() && landhard) {
4695 animTarget = getLandhard();
4708 void Person::DoStuff()
4710 static XYZ terrainnormal;
4711 static XYZ flatfacing;
4712 static XYZ flatvelocity;
4713 static float flatvelspeed;
4714 static int bloodsize;
4715 static int startx, starty, endx, endy;
4716 static GLubyte color;
4717 static XYZ bloodvel;
4719 onfiredelay -= multiplier;
4720 if (onfiredelay < 0 && onfire) {
4721 if (Random() % 2 == 0) {
4727 crouchkeydowntime += multiplier;
4728 if (!crouchkeydown) {
4729 crouchkeydowntime = 0;
4731 jumpkeydowntime += multiplier;
4732 if (!jumpkeydown && skeleton.free) {
4733 jumpkeydowntime = 0;
4736 if (hostile || damage > 0 || bloodloss > 0) {
4740 if (isIdle() || isRun()) {
4744 if (num_weapons == 1 && weaponactive != -1) {
4749 blooddimamount -= multiplier * .3;
4751 speechdelay -= multiplier;
4752 texupdatedelay -= multiplier;
4753 interestdelay -= multiplier;
4754 flamedelay -= multiplier;
4755 parriedrecently -= multiplier;
4757 victim = this->shared_from_this();
4762 speed = 1.1 * speedmult;
4764 speed = 1.0 * speedmult;
4766 if (!skeleton.free) {
4767 rabbitkickragdoll = 0;
4772 if (id != 0 && (creature == rabbittype || difficulty != 2)) {
4775 if (id != 0 && creature == wolftype && difficulty == 2) {
4777 if (aitype != passivetype) {
4779 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) {
4786 if (animTarget == wolfrunninganim && !superruntoggle) {
4787 animTarget = getRun();
4791 if (weaponactive == -1 && num_weapons > 0) {
4792 if (weapons[weaponids[0]].getType() == staff) {
4798 burnt += multiplier;
4803 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4805 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4812 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
4813 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4817 while (flamedelay < 0 && onfire) {
4819 int howmany = fabs(Random() % (skeleton.joints.size()));
4820 if (skeleton.free) {
4821 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4822 flatfacing = skeleton.joints[howmany].position * scale + coords;
4824 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4825 flatvelocity = (coords - oldcoords) / multiplier / 2;
4827 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4830 while (flamedelay < 0 && !onfire && Tutorial::active && id != 0) {
4832 int howmany = fabs(Random() % (skeleton.joints.size()));
4833 if (skeleton.free) {
4834 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4835 flatfacing = skeleton.joints[howmany].position * scale + coords;
4837 flatvelocity = (coords - oldcoords) / multiplier / 2;
4838 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4840 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4844 bleeding -= multiplier * .3;
4845 if (bloodtoggle == 2) {
4846 skeleton.drawmodel.textureptr.bind();
4847 if ((bleeding <= 0) && (detail != 2)) {
4853 if (neckspurtamount > 0) {
4854 neckspurtamount -= multiplier;
4855 neckspurtdelay -= multiplier * 3;
4856 neckspurtparticledelay -= multiplier * 3;
4857 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4860 if (skeleton.free) {
4861 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4862 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4863 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4865 bloodvel.z = 5 * neckspurtamount;
4866 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4867 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4868 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4870 neckspurtparticledelay = .05;
4872 if (neckspurtdelay < 0) {
4877 if (deathbleeding > 0 && dead != 2) {
4878 if (deathbleeding < 5) {
4879 bleeddelay -= deathbleeding * multiplier / 4;
4881 bleeddelay -= 5 * multiplier / 4;
4883 if (bleeddelay < 0 && bloodtoggle) {
4888 if (skeleton.free) {
4889 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4890 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4892 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4893 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4897 bloodloss += deathbleeding * multiplier * 80;
4898 deathbleeding -= multiplier * 1.6;
4899 if (deathbleeding < 0) {
4902 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4903 if (weaponactive != -1) {
4904 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4905 weapons[weaponids[0]].velocity.x += .01;
4908 weaponids[0] = weaponids[num_weapons];
4909 if (weaponstuck == num_weapons) {
4914 for (unsigned i = 0; i < Person::players.size(); i++) {
4915 Person::players[i]->wentforweapon = 0;
4923 if (!dead && creature == wolftype) {
4924 award_bonus(0, Wolfbonus);
4927 if (animTarget == knifefollowedanim && !skeleton.free) {
4928 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4929 skeleton.joints[i].velocity = 0;
4930 skeleton.joints[i].velocity.y = -2;
4933 if (id != 0 && unconscioustime > .1) {
4941 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4942 texupdatedelay = .12;
4944 bloodsize = 5 - realtexdetail;
4948 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4949 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4950 endx = startx + bloodsize;
4951 endy = starty + bloodsize;
4961 if (endx > skeleton.skinsize - 1) {
4962 endx = skeleton.skinsize - 1;
4965 if (endy > skeleton.skinsize - 1) {
4966 endy = skeleton.skinsize - 1;
4969 if (endx < startx) {
4972 if (endy < starty) {
4976 for (int i = startx; i < endx; i++) {
4977 for (int j = starty; j < endy; j++) {
4978 if (Random() % 2 == 0) {
4979 color = Random() % 85 + 170;
4980 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2) {
4981 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4983 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4984 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4989 skeleton.drawmodel.textureptr.bind();
4993 if (skeleton.free) {
4994 bleedx += 4 * direction / realtexdetail;
4996 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4998 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
5001 bleedy -= 4 / realtexdetail;
5003 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
5005 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
5010 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
5011 righthandmorphness = targetrighthandmorphness;
5012 righthandmorphstart = righthandmorphend;
5013 } else if (righthandmorphness > targetrighthandmorphness) {
5014 righthandmorphness -= multiplier * 4;
5015 } else if (righthandmorphness < targetrighthandmorphness) {
5016 righthandmorphness += multiplier * 4;
5019 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
5020 lefthandmorphness = targetlefthandmorphness;
5021 lefthandmorphstart = lefthandmorphend;
5022 } else if (lefthandmorphness > targetlefthandmorphness) {
5023 lefthandmorphness -= multiplier * 4;
5024 } else if (lefthandmorphness < targetlefthandmorphness) {
5025 lefthandmorphness += multiplier * 4;
5028 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
5029 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
5030 tailmorphness = targettailmorphness;
5031 tailmorphstart = tailmorphend;
5032 } else if (tailmorphness > targettailmorphness) {
5033 tailmorphness -= multiplier * 10;
5034 } else if (tailmorphness < targettailmorphness) {
5035 tailmorphness += multiplier * 10;
5039 if (creature == wolftype) {
5040 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
5041 tailmorphness = targettailmorphness;
5042 tailmorphstart = tailmorphend;
5043 } else if (tailmorphness > targettailmorphness) {
5044 tailmorphness -= multiplier * 2;
5045 } else if (tailmorphness < targettailmorphness) {
5046 tailmorphness += multiplier * 2;
5050 if (headmorphend == 3 || headmorphstart == 3) {
5051 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
5052 headmorphness = targetheadmorphness;
5053 headmorphstart = headmorphend;
5054 } else if (headmorphness > targetheadmorphness) {
5055 headmorphness -= multiplier * 7;
5056 } else if (headmorphness < targetheadmorphness) {
5057 headmorphness += multiplier * 7;
5059 } else if (headmorphend == 5 || headmorphstart == 5) {
5060 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
5061 headmorphness = targetheadmorphness;
5062 headmorphstart = headmorphend;
5063 } else if (headmorphness > targetheadmorphness) {
5064 headmorphness -= multiplier * 10;
5065 } else if (headmorphness < targetheadmorphness) {
5066 headmorphness += multiplier * 10;
5069 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
5070 headmorphness = targetheadmorphness;
5071 headmorphstart = headmorphend;
5072 } else if (headmorphness > targetheadmorphness) {
5073 headmorphness -= multiplier * 4;
5074 } else if (headmorphness < targetheadmorphness) {
5075 headmorphness += multiplier * 4;
5079 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
5080 chestmorphness = targetchestmorphness;
5081 chestmorphstart = chestmorphend;
5082 } else if (chestmorphness > targetchestmorphness) {
5083 chestmorphness -= multiplier;
5084 } else if (chestmorphness < targetchestmorphness) {
5085 chestmorphness += multiplier;
5088 if (dead != 2 && howactive <= typesleeping) {
5089 if (chestmorphstart == 0 && chestmorphend == 0) {
5091 targetchestmorphness = 1;
5094 if (chestmorphstart != 0 && chestmorphend != 0) {
5096 targetchestmorphness = 1;
5098 if (environment == snowyenvironment) {
5101 if (skeleton.free) {
5102 footvel = skeleton.specialforward[0] * -1;
5103 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
5105 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
5106 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
5108 if (animTarget == sleepanim) {
5109 footvel = DoRotation(footvel, 0, 90, 0);
5111 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
5115 if (!dead && howactive < typesleeping) {
5116 blinkdelay -= multiplier * 2;
5117 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
5119 targetheadmorphness = 1;
5121 blinkdelay = (float)(abs(Random() % 40)) / 5;
5123 if (headmorphstart == 3 && headmorphend == 3) {
5125 targetheadmorphness = 1;
5130 twitchdelay -= multiplier * 1.5;
5131 if (animTarget != hurtidleanim) {
5132 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
5134 targetheadmorphness = 1;
5136 twitchdelay = (float)(abs(Random() % 40)) / 5;
5138 if (headmorphstart == 5 && headmorphend == 5) {
5140 targetheadmorphness = 1;
5144 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
5145 twitchdelay3 -= multiplier * 1;
5146 if (Random() % 2 == 0) {
5147 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
5148 righthandmorphness = 0;
5149 targetrighthandmorphness = 1;
5150 righthandmorphend = 1;
5151 if (Random() % 2 == 0) {
5152 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
5155 if (righthandmorphstart == 1 && righthandmorphend == 1) {
5156 righthandmorphness = 0;
5157 targetrighthandmorphness = 1;
5158 righthandmorphend = 0;
5161 if (Random() % 2 == 0) {
5162 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
5163 lefthandmorphness = 0;
5164 targetlefthandmorphness = 1;
5165 lefthandmorphend = 1;
5166 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
5168 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
5169 lefthandmorphness = 0;
5170 targetlefthandmorphness = 1;
5171 lefthandmorphend = 0;
5177 if (creature == rabbittype) {
5178 if (howactive < typesleeping) {
5179 twitchdelay2 -= multiplier * 1.5;
5181 twitchdelay2 -= multiplier * 0.5;
5183 if (howactive <= typesleeping) {
5184 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
5186 targettailmorphness = 1;
5188 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
5190 if (tailmorphstart == 1 && tailmorphend == 1) {
5192 targettailmorphness = 1;
5195 if (tailmorphstart == 2 && tailmorphend == 2) {
5197 targettailmorphness = 1;
5204 if (creature == wolftype) {
5205 twitchdelay2 -= multiplier * 1.5;
5206 if (tailmorphend != 0) {
5207 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
5209 targettailmorphness = 1;
5214 if (tailmorphend != 5) {
5215 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
5217 targettailmorphness = 1;
5222 if (twitchdelay2 <= 0) {
5223 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
5225 targettailmorphness = 1;
5228 if (tailmorphstart == 1 && tailmorphend == 1) {
5230 targettailmorphness = 1;
5233 if (tailmorphstart == 2 && tailmorphend == 2) {
5235 targettailmorphness = 1;
5238 if (tailmorphstart == 3 && tailmorphend == 3) {
5240 targettailmorphness = 1;
5243 if (tailmorphstart == 4 && tailmorphend == 4) {
5245 targettailmorphness = 1;
5252 unconscioustime = 0;
5255 if (dead == 1 || howactive == typesleeping) {
5256 unconscioustime += multiplier;
5257 //If unconscious, close eyes and mouth
5258 if (righthandmorphend != 0) {
5259 righthandmorphness = 0;
5261 righthandmorphend = 0;
5262 targetrighthandmorphness = 1;
5264 if (lefthandmorphend != 0) {
5265 lefthandmorphness = 0;
5267 lefthandmorphend = 0;
5268 targetlefthandmorphness = 1;
5270 if (headmorphend != 3 && headmorphend != 5) {
5274 targetheadmorphness = 1;
5277 if (howactive > typesleeping) {
5280 if (bloodtoggle && !bled) {
5281 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5282 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5283 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5284 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5288 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5294 if (dead == 2 || howactive > typesleeping) {
5295 //If dead, open mouth and hands
5296 if (righthandmorphend != 0) {
5297 righthandmorphness = 0;
5299 righthandmorphend = 0;
5300 targetrighthandmorphness = 1;
5302 if (lefthandmorphend != 0) {
5303 lefthandmorphness = 0;
5305 lefthandmorphend = 0;
5306 targetlefthandmorphness = 1;
5308 if (headmorphend != 2) {
5312 targetheadmorphness = 1;
5315 if (stunned > 0 && !dead && headmorphend != 2) {
5316 if (headmorphend != 4) {
5320 targetheadmorphness = 1;
5323 if (damage > damagetolerance && !dead) {
5326 unconscioustime = 0;
5328 if (creature == wolftype) {
5329 award_bonus(0, Wolfbonus);
5334 if (weaponactive != -1) {
5335 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5336 weapons[weaponids[0]].velocity.x += .01;
5339 weaponids[0] = weaponids[num_weapons];
5340 if (weaponstuck == num_weapons) {
5345 for (unsigned i = 0; i < Person::players.size(); i++) {
5346 Person::players[i]->wentforweapon = 0;
5350 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
5359 damage -= multiplier * 13;
5360 permanentdamage -= multiplier * 4;
5361 if (isIdle() || isCrouch()) {
5362 permanentdamage -= multiplier * 4;
5368 if (permanentdamage < 0) {
5369 permanentdamage = 0;
5371 if (superpermanentdamage < 0) {
5372 superpermanentdamage = 0;
5374 if (permanentdamage < superpermanentdamage) {
5375 permanentdamage = superpermanentdamage;
5377 if (damage < permanentdamage) {
5378 damage = permanentdamage;
5380 if (dead == 1 && damage < damagetolerance) {
5384 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5385 skeleton.joints[i].velocity = 0;
5388 if (permanentdamage > damagetolerance && dead != 2) {
5391 if (weaponactive != -1) {
5392 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5393 weapons[weaponids[0]].velocity.x += .01;
5396 weaponids[0] = weaponids[num_weapons];
5397 if (weaponstuck == num_weapons) {
5402 for (unsigned i = 0; i < Person::players.size(); i++) {
5403 Person::players[i]->wentforweapon = 0;
5409 if (!dead && creature == wolftype) {
5410 award_bonus(0, Wolfbonus);
5413 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance) {
5414 award_bonus(id, touchofdeath);
5416 if (id != 0 && unconscioustime > .1) {
5424 emit_sound_at(breaksound, coords);
5427 if (skeleton.free == 1) {
5429 pause_sound(whooshsound);
5433 //If knocked over, open hands and close mouth
5434 if (righthandmorphend != 0) {
5435 righthandmorphness = 0;
5437 righthandmorphend = 0;
5438 targetrighthandmorphness = 1;
5440 if (lefthandmorphend != 0) {
5441 lefthandmorphness = 0;
5443 lefthandmorphend = 0;
5444 targetlefthandmorphness = 1;
5446 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
5447 if (headmorphend != 0) {
5451 targetheadmorphness = 1;
5455 skeleton.DoGravity(&scale);
5457 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
5458 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1)) {
5459 award_bonus(id, deepimpact);
5461 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5465 if (!skeleton.joints.empty()) {
5466 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5467 average += skeleton.joints[j].position;
5469 average /= skeleton.joints.size();
5470 coords += average * scale;
5471 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5472 skeleton.joints[j].position -= average;
5474 average /= multiplier;
5478 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5479 velocity += skeleton.joints[i].velocity * scale;
5481 velocity /= skeleton.joints.size();
5483 if (!isnormal(velocity.x) && velocity.x) {
5487 if (findLength(&average) < 10 && dead && skeleton.free) {
5488 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5489 if (skeleton.longdead > 2000) {
5490 if (skeleton.longdead > 6000) {
5492 pause_sound(whooshsound);
5498 if (dead == 2 && bloodloss < damagetolerance) {
5500 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5502 if (bloodtoggle && !bled) {
5503 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5504 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5505 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5506 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5507 float size = .2 * 1.2;
5510 Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5515 if (dead == 2 && bloodloss >= damagetolerance) {
5517 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5518 if (bleeding <= 0) {
5521 if (bloodtoggle && !bled) {
5522 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5523 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5524 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5525 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5529 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5537 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5538 bool canrecover = 1;
5539 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5540 startpoint = coords;
5543 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1) {
5546 if (velocity.y < -30) {
5549 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5550 if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) {
5551 colviewer = startpoint;
5552 coltarget = endpoint;
5553 if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1) {
5563 terrainnormal = jointPos(groin) - jointPos(abdomen);
5564 if (joint(groin).locked && joint(abdomen).locked) {
5565 terrainnormal = jointPos(groin) - jointPos(abdomen);
5566 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5568 if (joint(abdomen).locked && joint(neck).locked) {
5569 terrainnormal = jointPos(abdomen) - jointPos(neck);
5570 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5572 if (joint(groin).locked && joint(neck).locked) {
5573 terrainnormal = jointPos(groin) - jointPos(neck);
5574 middle = (jointPos(groin) + jointPos(neck)) / 2;
5576 Normalise(&terrainnormal);
5578 targetyaw = -asin(0 - terrainnormal.x);
5579 targetyaw *= 360 / 6.28;
5580 if (terrainnormal.z < 0) {
5581 targetyaw = 180 - targetyaw;
5586 animTarget = flipanim;
5587 crouchtogglekeydown = 1;
5592 animCurrent = tempanim;
5596 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5597 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5598 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5603 if (findLength(&average) < 10 && !dead && skeleton.free) {
5604 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5605 if (skeleton.longdead > (damage + 500) * 1.5) {
5607 pause_sound(whooshsound);
5614 terrainnormal = jointPos(groin) - jointPos(abdomen);
5615 if (joint(groin).locked && joint(abdomen).locked) {
5616 terrainnormal = jointPos(groin) - jointPos(abdomen);
5617 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5619 if (joint(abdomen).locked && joint(neck).locked) {
5620 terrainnormal = jointPos(abdomen) - jointPos(neck);
5621 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5623 if (joint(groin).locked && joint(neck).locked) {
5624 terrainnormal = jointPos(groin) - jointPos(neck);
5625 middle = (jointPos(groin) + jointPos(neck)) / 2;
5627 Normalise(&terrainnormal);
5629 targetyaw = -asin(0 - terrainnormal.x);
5630 targetyaw *= 360 / 6.28;
5631 if (terrainnormal.z < 0) {
5632 targetyaw = 180 - targetyaw;
5636 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5638 if (skeleton.forward.y < 0) {
5639 animTarget = getupfrombackanim;
5643 if (skeleton.forward.y > -.3) {
5644 animTarget = getupfromfrontanim;
5652 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5653 animTarget = rollanim;
5654 targetyaw = lookyaw;
5658 if (forwardkeydown) {
5667 if (forwardkeydown) {
5675 if (!leftkeydown && !rightkeydown) {
5683 if (abs(targettilt2) > 50) {
5686 animCurrent = tempanim;
5689 tilt2 = targettilt2;
5691 if (middle.y > 0 && animTarget != rollanim) {
5692 targetoffset.y = middle.y + 1;
5695 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5696 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5697 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5704 if (num_weapons > 0) {
5705 if (weapons[0].getType() == staff) {
5709 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5710 if (velocity.y > -30) {
5712 tempvelocity = velocity;
5713 Normalise(&tempvelocity);
5714 targetyaw = -asin(0 - tempvelocity.x);
5715 targetyaw *= 360 / 6.28;
5716 if (velocity.z < 0) {
5717 targetyaw = 180 - targetyaw;
5722 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5723 animTarget = rollanim;
5726 animTarget = backhandspringanim;
5732 emit_sound_at(movewhooshsound, coords, 128.);
5734 animCurrent = animTarget;
5735 frameCurrent = frameTarget - 1;
5747 if (skeleton.freefall == 0) {
5752 if (aitype != passivetype || skeleton.free == 1) {
5753 if (findLengthfast(&velocity) > .1) {
5754 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5755 if (Object::objects[i]->type == firetype) {
5756 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) {
5758 if (!Object::objects[i]->onfire) {
5759 emit_sound_at(firestartsound, Object::objects[i]->position);
5761 Object::objects[i]->onfire = 1;
5764 if (Object::objects[i]->onfire) {
5770 if (Object::objects[i]->type == bushtype) {
5771 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) {
5773 if (!Object::objects[i]->onfire) {
5774 emit_sound_at(firestartsound, Object::objects[i]->position);
5776 Object::objects[i]->onfire = 1;
5780 if (Object::objects[i]->onfire) {
5784 if (Object::objects[i]->messedwith <= 0) {
5788 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5791 addEnvSound(coords, 4 * findLength(&velocity));
5795 if (environment == grassyenvironment) {
5796 howmany = findLength(&velocity) * 4;
5798 if (environment == snowyenvironment) {
5799 howmany = findLength(&velocity) * 2;
5802 if (environment != desertenvironment) {
5803 for (int j = 0; j < howmany; j++) {
5804 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5805 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5806 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5809 pos.x += float(abs(Random() % 100) - 50) / 200;
5810 pos.y += float(abs(Random() % 100) - 50) / 200;
5811 pos.z += float(abs(Random() % 100) - 50) / 200;
5812 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);
5813 Sprite::setLastSpriteSpecial(1);
5817 howmany = findLength(&velocity) * 4;
5819 if (environment == snowyenvironment) {
5820 for (int j = 0; j < howmany; j++) {
5821 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5822 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5823 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5826 pos.x += float(abs(Random() % 100) - 50) / 200;
5827 pos.y += float(abs(Random() % 100) - 50) / 200;
5828 pos.z += float(abs(Random() % 100) - 50) / 200;
5829 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5830 Sprite::setLastSpriteSpecial(2);
5835 Object::objects[i]->rotx += velocity.x * multiplier * 6;
5836 Object::objects[i]->roty += velocity.z * multiplier * 6;
5837 Object::objects[i]->messedwith = .5;
5841 if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) {
5842 if (Object::objects[i]->pitch == 0) {
5845 tempcoord = coords - Object::objects[i]->position;
5846 tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0);
5847 tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0);
5848 tempcoord += Object::objects[i]->position;
5850 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) {
5851 if (Object::objects[i]->messedwith <= 0) {
5855 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5858 addEnvSound(coords, 4 * findLength(&velocity));
5862 if (environment == grassyenvironment) {
5863 howmany = findLength(&velocity) * 4;
5865 if (environment == snowyenvironment) {
5866 howmany = findLength(&velocity) * 2;
5869 if (environment != desertenvironment) {
5870 for (int j = 0; j < howmany; j++) {
5871 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5872 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5873 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5875 pos += velocity * .1;
5877 pos.x += float(abs(Random() % 100) - 50) / 150;
5878 pos.y += float(abs(Random() % 100) - 50) / 150;
5879 pos.z += float(abs(Random() % 100) - 50) / 150;
5880 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);
5881 Sprite::setLastSpriteSpecial(1);
5885 howmany = findLength(&velocity) * 4;
5887 if (environment == snowyenvironment) {
5888 for (int j = 0; j < howmany; j++) {
5889 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5890 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5891 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5893 pos += velocity * .1;
5895 pos.x += float(abs(Random() % 100) - 50) / 150;
5896 pos.y += float(abs(Random() % 100) - 50) / 150;
5897 pos.z += float(abs(Random() % 100) - 50) / 150;
5898 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5899 Sprite::setLastSpriteSpecial(2);
5904 Object::objects[i]->messedwith = .5;
5911 if (!skeleton.free) {
5914 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype) {
5918 if (aitype != passivetype && victim->skeleton.free && !victim->dead) {
5922 if (Tutorial::active && id != 0) {
5925 if (play && aitype != playercontrolled) {
5926 int whichsound = -1;
5927 if (speechdelay <= 0) {
5928 unsigned int i = abs(Random() % 4);
5929 if (creature == rabbittype) {
5931 whichsound = rabbitchitter;
5934 whichsound = rabbitchitter2;
5937 if (creature == wolftype) {
5939 whichsound = growlsound;
5942 whichsound = growl2sound;
5948 if (whichsound != -1) {
5949 emit_sound_at(whichsound, coords);
5953 if (animTarget == staggerbackhighanim) {
5956 if (animTarget == staggerbackhardanim) {
5959 staggerdelay -= multiplier;
5960 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
5963 if (velocity.y < -30 && animTarget == jumpdownanim) {
5966 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5967 animTarget = getIdle();
5971 weaponmissdelay -= multiplier;
5972 highreversaldelay -= multiplier;
5973 lowreversaldelay -= multiplier;
5974 lastcollide -= multiplier;
5975 skiddelay -= multiplier;
5976 if (!isnormal(velocity.x) && velocity.x) {
5979 if (!isnormal(targettilt) && targettilt) {
5982 if (!isnormal(targettilt2) && targettilt2) {
5985 if (!isnormal(targetyaw) && targetyaw) {
5989 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5990 //open hands and close mouth
5991 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5992 righthandmorphness = 0;
5993 righthandmorphend = 0;
5994 targetrighthandmorphness = 1;
5997 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5998 lefthandmorphness = 0;
5999 lefthandmorphend = 0;
6000 targetlefthandmorphness = 1;
6003 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
6006 targetheadmorphness = 1;
6010 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) {
6011 //open hands and mouth
6012 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
6013 righthandmorphness = 0;
6014 righthandmorphend = 0;
6015 targetrighthandmorphness = 1;
6018 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
6019 lefthandmorphness = 0;
6020 lefthandmorphend = 0;
6021 targetlefthandmorphness = 1;
6024 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
6027 targetheadmorphness = 1;
6031 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
6032 //close hands and mouth
6033 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
6034 righthandmorphness = 0;
6035 righthandmorphend = 1;
6036 targetrighthandmorphness = 1;
6039 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
6040 lefthandmorphness = 0;
6041 lefthandmorphend = 1;
6042 targetlefthandmorphness = 1;
6045 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
6048 targetheadmorphness = 1;
6052 if (animTarget == spinkickanim ||
6053 animTarget == staffspinhitreversalanim ||
6054 animTarget == staffspinhitreversedanim ||
6055 animTarget == staffhitreversalanim ||
6056 animTarget == staffhitreversedanim ||
6057 animTarget == hurtidleanim ||
6058 animTarget == winduppunchanim ||
6059 animTarget == swordslashreversalanim ||
6060 animTarget == swordslashreversedanim ||
6061 animTarget == knifeslashreversalanim ||
6062 animTarget == knifeslashreversedanim ||
6063 animTarget == knifethrowanim ||
6064 animTarget == knifefollowanim ||
6065 animTarget == knifefollowedanim ||
6066 animTarget == killanim ||
6067 animTarget == dropkickanim ||
6068 animTarget == upunchanim ||
6069 animTarget == knifeslashstartanim ||
6070 animTarget == swordslashanim ||
6071 animTarget == staffhitanim ||
6072 animTarget == staffspinhitanim ||
6073 animTarget == staffgroundsmashanim ||
6074 animTarget == spinkickreversalanim ||
6075 animTarget == sweepreversalanim ||
6076 animTarget == lowkickanim ||
6077 animTarget == sweepreversedanim ||
6078 animTarget == rabbitkickreversalanim ||
6079 animTarget == rabbitkickreversedanim ||
6080 animTarget == jumpreversalanim ||
6081 animTarget == jumpreversedanim) {
6082 //close hands and yell
6083 if (righthandmorphend != 1 &&
6084 righthandmorphness == targetrighthandmorphness) {
6085 righthandmorphness = 0;
6086 righthandmorphend = 1;
6087 targetrighthandmorphness = 1;
6090 if (lefthandmorphend != 1 &&
6091 lefthandmorphness == targetlefthandmorphness) {
6092 lefthandmorphness = 0;
6093 lefthandmorphend = 1;
6094 targetlefthandmorphness = 1;
6097 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
6100 targetheadmorphness = 1;
6107 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
6108 (victim->aitype != searchtype) && (aitype != passivetype) &&
6109 (aitype != searchtype) && (victim->id < Person::players.size())) {
6110 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
6114 if (!dead && animTarget != hurtidleanim) {
6115 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
6116 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
6119 targetheadmorphness = 1;
6124 if (weaponactive != -1) {
6125 if (weapons[weaponids[weaponactive]].getType() != staff) {
6126 righthandmorphstart = 1;
6127 righthandmorphend = 1;
6129 if (weapons[weaponids[weaponactive]].getType() == staff) {
6130 righthandmorphstart = 2;
6131 righthandmorphend = 2;
6133 targetrighthandmorphness = 1;
6136 terrainnormal = terrain.getNormal(coords.x, coords.z);
6138 if (Animation::animations[animTarget].attack != reversal) {
6139 if (!isnormal(coords.x)) {
6148 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
6149 facing = flatfacing;
6150 ReflectVector(&facing, terrainnormal);
6154 animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
6156 targettilt2 = -facing.y * 20;
6162 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim) {
6165 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6166 flatvelocity = velocity;
6168 flatvelspeed = findLength(&flatvelocity);
6169 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
6170 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
6171 if (velocity.y < 0) {
6174 if (velocity.y < 0) {
6177 if (targettilt > 25) {
6180 if (targettilt < -25) {
6185 if (targettilt2 > 45) {
6188 if (targettilt2 < -45) {
6191 if (abs(tilt2 - targettilt2) < multiplier * 400) {
6192 tilt2 = targettilt2;
6193 } else if (tilt2 > targettilt2) {
6194 tilt2 -= multiplier * 400;
6195 } else if (tilt2 < targettilt2) {
6196 tilt2 += multiplier * 400;
6198 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
6207 if (!isnormal(targettilt) && targettilt) {
6210 if (!isnormal(targettilt2) && targettilt2) {
6215 if (animTarget == rabbittackleanim) {
6216 velocity += facing * multiplier * speed * 700 * scale;
6217 velspeed = findLength(&velocity);
6218 if (velspeed > speed * 65 * scale) {
6219 velocity /= velspeed;
6220 velspeed = speed * 65 * scale;
6221 velocity *= velspeed;
6223 velocity.y += gravity * multiplier * 20;
6224 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6225 velspeed = findLength(&velocity);
6226 velocity = flatfacing * velspeed;
6228 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
6229 if (isRun() || animTarget == rabbitkickanim) {
6230 velocity += facing * multiplier * speed * 700 * scale;
6231 velspeed = findLength(&velocity);
6232 if (velspeed > speed * 45 * scale) {
6233 velocity /= velspeed;
6234 velspeed = speed * 45 * scale;
6235 velocity *= velspeed;
6237 velocity.y += gravity * multiplier * 20;
6238 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6239 velspeed = findLength(&velocity);
6240 if (velspeed < speed * 30 * scale) {
6241 velspeed = speed * 30 * scale;
6243 velocity = flatfacing * velspeed;
6245 } else if (isRun()) {
6246 velocity += facing * multiplier * speed * 700 * scale;
6247 velspeed = findLength(&velocity);
6248 if (creature == rabbittype) {
6249 if (velspeed > speed * 55 * scale) {
6250 velocity /= velspeed;
6251 velspeed = speed * 55 * scale;
6252 velocity *= velspeed;
6255 if (creature == wolftype) {
6256 if (velspeed > speed * 75 * scale) {
6257 velocity /= velspeed;
6258 velspeed = speed * 75 * scale;
6259 velocity *= velspeed;
6262 velocity.y += gravity * multiplier * 20;
6263 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6264 velspeed = findLength(&velocity);
6265 velocity = flatfacing * velspeed;
6268 if (animTarget == rollanim && targetFrame().label != 6) {
6269 velocity += facing * multiplier * speed * 700 * scale;
6270 velspeed = findLength(&velocity);
6271 if (velspeed > speed * 45 * scale) {
6272 velocity /= velspeed;
6273 velspeed = speed * 45 * scale;
6274 velocity *= velspeed;
6276 velocity.y += gravity * multiplier * 20;
6277 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6278 velspeed = findLength(&velocity);
6279 velocity = flatfacing * velspeed;
6282 if (animTarget == sneakanim || animTarget == walkanim) {
6283 velocity += facing * multiplier * speed * 700 * scale;
6284 velspeed = findLength(&velocity);
6285 if (velspeed > speed * 12 * scale) {
6286 velocity /= velspeed;
6287 velspeed = speed * 12 * scale;
6288 velocity *= velspeed;
6290 velocity.y += gravity * multiplier * 20;
6291 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6292 velspeed = findLength(&velocity);
6293 velocity = flatfacing * velspeed;
6296 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
6297 velocity += facing * multiplier * speed * 700 * scale;
6298 velspeed = findLength(&velocity);
6299 if (velspeed > speed * 2 * scale) {
6300 velocity /= velspeed;
6301 velspeed = speed * 2 * scale;
6302 velocity *= velspeed;
6304 velocity.y += gravity * multiplier * 20;
6305 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6306 velspeed = findLength(&velocity);
6307 velocity = flatfacing * velspeed;
6310 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
6311 velocity -= facing * multiplier * speed * 700 * scale;
6312 velspeed = findLength(&velocity);
6313 if (velspeed > speed * 2 * scale) {
6314 velocity /= velspeed;
6315 velspeed = speed * 2 * scale;
6316 velocity *= velspeed;
6318 velocity.y += gravity * multiplier * 20;
6319 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6320 velspeed = findLength(&velocity);
6321 velocity = flatfacing * velspeed * -1;
6324 if (animTarget == fightsidestep) {
6325 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
6326 velspeed = findLength(&velocity);
6327 if (velspeed > speed * 12 * scale) {
6328 velocity /= velspeed;
6329 velspeed = speed * 12 * scale;
6330 velocity *= velspeed;
6332 velocity.y += gravity * multiplier * 20;
6333 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6334 velspeed = findLength(&velocity);
6335 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
6338 if (animTarget == staggerbackhighanim) {
6339 coords -= facing * multiplier * speed * 16 * scale;
6342 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
6343 coords -= facing * multiplier * speed * 20 * scale;
6347 if (animTarget == backhandspringanim) {
6348 //coords-=facing*multiplier*50*scale;
6349 velocity += facing * multiplier * speed * 700 * scale * -1;
6350 velspeed = findLength(&velocity);
6351 if (velspeed > speed * 50 * scale) {
6352 velocity /= velspeed;
6353 velspeed = speed * 50 * scale;
6354 velocity *= velspeed;
6356 velocity.y += gravity * multiplier * 20;
6357 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6358 velspeed = findLength(&velocity);
6359 velocity = flatfacing * velspeed * -1;
6361 if (animTarget == dodgebackanim) {
6362 //coords-=facing*multiplier*50*scale;
6363 velocity += facing * multiplier * speed * 700 * scale * -1;
6364 velspeed = findLength(&velocity);
6365 if (velspeed > speed * 60 * scale) {
6366 velocity /= velspeed;
6367 velspeed = speed * 60 * scale;
6368 velocity *= velspeed;
6370 velocity.y += gravity * multiplier * 20;
6371 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6372 velspeed = findLength(&velocity);
6373 velocity = flatfacing * velspeed * -1;
6376 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6377 velspeed = findLength(&velocity);
6380 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6381 velocity.y += gravity * multiplier;
6384 if (animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6385 coords += velocity * multiplier;
6388 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6389 if (isFlip() && targetFrame().label == 7) {
6393 if (animTarget == jumpupanim) {
6395 animTarget = getIdle();
6402 pause_sound(whooshsound);
6403 OPENAL_SetVolume(channels[whooshsound], 0);
6406 if (animTarget == jumpdownanim || isFlip()) {
6410 animTarget = getLanding();
6411 emit_sound_at(landsound, coords, 128.);
6414 addEnvSound(coords);
6419 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6420 coords.y += gravity * multiplier * 2;
6422 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
6423 coords.y = terrain.getHeight(coords.x, coords.z);
6427 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)) {
6428 velspeed = findLength(&velocity);
6430 if (velspeed < multiplier * 300 * scale) {
6433 velocity -= velocity / velspeed * multiplier * 300 * scale;
6435 if (velspeed > 5 && (isLanding() || isLandhard())) {
6436 skiddingdelay += multiplier;
6437 if (skiddelay <= 0) {
6438 FootLand(leftfoot, .5);
6439 FootLand(rightfoot, .5);
6448 velspeed = findLength(&velocity);
6450 if (velspeed > 5 && (isLanding() || isLandhard())) {
6451 skiddingdelay += multiplier;
6452 if (skiddelay <= 0) {
6453 FootLand(leftfoot, .5);
6454 FootLand(rightfoot, .5);
6462 if (skiddingdelay < 0) {
6463 skiddingdelay += multiplier;
6465 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
6467 if (!onterrain || environment == grassyenvironment) {
6468 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
6470 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
6474 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
6475 terrainnormal = victim->coords - coords;
6476 Normalise(&terrainnormal);
6477 targetyaw = -asin(0 - terrainnormal.x);
6478 targetyaw *= 360 / 6.28;
6479 if (terrainnormal.z < 0) {
6480 targetyaw = 180 - targetyaw;
6482 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
6485 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
6486 targetyaw = victim->targetyaw;
6488 if (animTarget == rabbittacklinganim) {
6489 coords = victim->coords;
6492 skeleton.oldfree = skeleton.free;
6496 midterrain.x = terrain.size * terrain.scale / 2;
6497 midterrain.z = terrain.size * terrain.scale / 2;
6498 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
6500 tempposit = coords - midterrain;
6502 Normalise(&tempposit);
6503 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
6504 coords.x = tempposit.x + midterrain.x;
6505 coords.z = tempposit.z + midterrain.z;
6510 * inverse kinematics helper function
6512 void IKHelper(Person* p, float interp)
6514 XYZ point, change, change2;
6515 float heightleft, heightright;
6517 // TODO: implement localToWorld and worldToLocal
6518 // but keep in mind it won't be the same math if player is ragdolled or something
6519 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
6520 // then comb through code for places where to use it
6522 // point = localToWorld(jointPos(leftfoot))
6523 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
6524 // adjust height of foot
6525 heightleft = terrain.getHeight(point.x, point.z) + .04;
6526 point.y = heightleft;
6527 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
6528 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
6529 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
6530 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
6531 // move ankle along with foot
6532 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
6533 // average knee pos between old and new pos
6534 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
6536 // do same as above for right leg
6537 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
6538 heightright = terrain.getHeight(point.x, point.z) + .04;
6539 point.y = heightright;
6540 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
6541 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
6542 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
6543 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
6544 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
6546 // fix up skeleton now that we've moved body parts?
6547 p->skeleton.DoConstraints(&p->coords, &p->scale);
6554 int Person::DrawSkeleton()
6556 int oldplayerdetail;
6557 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6558 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6568 glAlphaFunc(GL_GREATER, 0.0001);
6570 float terrainheight;
6572 if (!isnormal(yaw)) {
6575 if (!isnormal(tilt)) {
6578 if (!isnormal(tilt2)) {
6581 oldplayerdetail = playerdetail;
6583 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6586 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6589 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6595 if (playerdetail != oldplayerdetail) {
6597 normalsupdatedelay = 0;
6599 static float updatedelaychange;
6600 static float morphness;
6601 static float framemult;
6603 skeleton.FindForwards();
6604 if (howactive == typesittingwall) {
6605 skeleton.specialforward[1] = 0;
6606 skeleton.specialforward[1].z = 1;
6612 static int weaponattachmuscle;
6613 static int weaponrotatemuscle;
6614 static XYZ weaponpoint;
6615 static int start, endthing;
6616 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6617 if (!isSleeping() && !isSitting()) {
6618 // TODO: give these meaningful names
6619 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6620 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard() || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6622 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6624 if (creature == wolftype) {
6629 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6630 IKHelper(this, target);
6631 if (creature == wolftype) {
6632 IKHelper(this, target);
6636 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6637 IKHelper(this, 1 - target);
6638 if (creature == wolftype) {
6639 IKHelper(this, 1 - target);
6644 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())) {
6647 targetheadyaw = -targetyaw;
6648 targetheadpitch = 0;
6649 if (Animation::animations[animTarget].attack == 3) {
6650 targetheadyaw += 180;
6653 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6654 skeleton.drawmodel.vertex[i] = 0;
6655 skeleton.drawmodel.vertex[i].y = 999;
6657 for (int i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6658 skeleton.drawmodellow.vertex[i] = 0;
6659 skeleton.drawmodellow.vertex[i].y = 999;
6661 for (int i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6662 skeleton.drawmodelclothes.vertex[i] = 0;
6663 skeleton.drawmodelclothes.vertex[i].y = 999;
6665 for (unsigned int i = 0; i < skeleton.muscles.size(); i++) {
6666 // convenience renames
6667 const int p1 = skeleton.muscles[i].parent1->label;
6668 const int p2 = skeleton.muscles[i].parent2->label;
6670 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6675 if (p1 == righthand || p2 == righthand) {
6676 morphness = righthandmorphness;
6677 start = righthandmorphstart;
6678 endthing = righthandmorphend;
6680 if (p1 == lefthand || p2 == lefthand) {
6681 morphness = lefthandmorphness;
6682 start = lefthandmorphstart;
6683 endthing = lefthandmorphend;
6685 if (p1 == head || p2 == head) {
6686 morphness = headmorphness;
6687 start = headmorphstart;
6688 endthing = headmorphend;
6690 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6691 morphness = chestmorphness;
6692 start = chestmorphstart;
6693 endthing = chestmorphend;
6695 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6696 morphness = tailmorphness;
6697 start = tailmorphstart;
6698 endthing = tailmorphend;
6701 skeleton.FindRotationMuscle(i, animTarget);
6703 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6704 glMatrixMode(GL_MODELVIEW);
6707 if (!skeleton.free) {
6708 glRotatef(tilt2, 1, 0, 0);
6710 if (!skeleton.free) {
6711 glRotatef(tilt, 0, 0, 1);
6714 glTranslatef(mid.x, mid.y, mid.z);
6716 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6717 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6719 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6720 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6722 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6723 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6725 if (playerdetail || skeleton.free == 3) {
6726 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6727 XYZ& v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6728 XYZ& v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6729 glMatrixMode(GL_MODELVIEW);
6731 if (p1 == abdomen || p2 == abdomen) {
6732 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(1).x,
6733 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(1).y,
6734 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(1).z);
6736 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6737 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(2).x,
6738 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(2).y,
6739 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(2).z);
6741 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6742 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(3).x,
6743 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(3).y,
6744 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(3).z);
6746 if (p1 == head || p2 == head) {
6747 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(0).x,
6748 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(0).y,
6749 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(0).z);
6751 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6752 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6753 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6754 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6758 if (!playerdetail || skeleton.free == 3) {
6759 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6760 XYZ& v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6761 glMatrixMode(GL_MODELVIEW);
6763 if (p1 == abdomen || p2 == abdomen) {
6764 glTranslatef(v0.x * getProportion(1).x,
6765 v0.y * getProportion(1).y,
6766 v0.z * getProportion(1).z);
6768 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6769 glTranslatef(v0.x * getProportion(2).x,
6770 v0.y * getProportion(2).y,
6771 v0.z * getProportion(2).z);
6773 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6774 glTranslatef(v0.x * getProportion(3).x,
6775 v0.y * getProportion(3).y,
6776 v0.z * getProportion(3).z);
6778 if (p1 == head || p2 == head) {
6779 glTranslatef(v0.x * getProportion(0).x,
6780 v0.y * getProportion(0).y,
6781 v0.z * getProportion(0).z);
6784 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6785 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6786 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6787 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6793 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6794 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6796 glMatrixMode(GL_MODELVIEW);
6799 if (!skeleton.free) {
6800 glRotatef(tilt2, 1, 0, 0);
6802 if (!skeleton.free) {
6803 glRotatef(tilt, 0, 0, 1);
6805 glTranslatef(mid.x, mid.y, mid.z);
6806 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6807 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6809 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6810 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6812 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6813 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6815 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6816 XYZ& v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6817 glMatrixMode(GL_MODELVIEW);
6819 if (p1 == abdomen || p2 == abdomen) {
6820 glTranslatef(v0.x * getProportion(1).x,
6821 v0.y * getProportion(1).y,
6822 v0.z * getProportion(1).z);
6824 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6825 glTranslatef(v0.x * getProportion(2).x,
6826 v0.y * getProportion(2).y,
6827 v0.z * getProportion(2).z);
6829 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6830 glTranslatef(v0.x * getProportion(3).x,
6831 v0.y * getProportion(3).y,
6832 v0.z * getProportion(3).z);
6834 if (p1 == head || p2 == head) {
6835 glTranslatef(v0.x * getProportion(0).x,
6836 v0.y * getProportion(0).y,
6837 v0.z * getProportion(0).z);
6839 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6840 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6841 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6842 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6847 updatedelay = 1 + (float)(Random() % 100) / 1000;
6849 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6850 normalsupdatedelay = 1;
6851 if (playerdetail || skeleton.free == 3) {
6852 skeleton.drawmodel.CalculateNormals(0);
6854 if (!playerdetail || skeleton.free == 3) {
6855 skeleton.drawmodellow.CalculateNormals(0);
6857 if (skeleton.clothes) {
6858 skeleton.drawmodelclothes.CalculateNormals(0);
6861 if (playerdetail || skeleton.free == 3) {
6862 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6864 if (!playerdetail || skeleton.free == 3) {
6865 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6867 if (skeleton.clothes) {
6868 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6873 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6874 if (updatedelaychange > -realmultiplier * 30) {
6875 updatedelaychange = -realmultiplier * 30;
6877 if (updatedelaychange > -framemult * 4) {
6878 updatedelaychange = -framemult * 4;
6880 if (skeleton.free == 1) {
6881 updatedelaychange *= 6;
6884 updatedelaychange *= 8;
6886 updatedelay += updatedelaychange;
6888 glMatrixMode(GL_MODELVIEW);
6890 glTranslatef(coords.x, coords.y - .02, coords.z);
6891 if (!skeleton.free) {
6892 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6893 glRotatef(yaw, 0, 1, 0);
6897 glColor4f(.4, 1, .4, 1);
6898 glDisable(GL_LIGHTING);
6899 glDisable(GL_TEXTURE_2D);
6902 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6903 XYZ& v0 = skeleton.drawmodel.vertex[i];
6904 glVertex3f(v0.x, v0.y, v0.z);
6911 for (unsigned int i = 0; i < skeleton.drawmodel.Triangles.size(); i++) {
6912 const XYZ& v0 = skeleton.drawmodel.getTriangleVertex(i, 0);
6913 const XYZ& v1 = skeleton.drawmodel.getTriangleVertex(i, 1);
6914 const XYZ& v2 = skeleton.drawmodel.getTriangleVertex(i, 2);
6915 glVertex3f(v0.x, v0.y, v0.z);
6916 glVertex3f(v1.x, v1.y, v1.z);
6917 glVertex3f(v1.x, v1.y, v1.z);
6918 glVertex3f(v2.x, v2.y, v2.z);
6919 glVertex3f(v2.x, v2.y, v2.z);
6920 glVertex3f(v0.x, v0.y, v0.z);
6927 terrainlight = terrain.getLighting(coords.x, coords.z);
6928 distance = distsq(&viewer, &coords);
6929 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6934 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6935 if (terrainheight < 1) {
6938 if (terrainheight > 1.7) {
6939 terrainheight = 1.7;
6942 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6943 glDisable(GL_BLEND);
6944 glAlphaFunc(GL_GREATER, 0.0001);
6945 glEnable(GL_TEXTURE_2D);
6947 glDisable(GL_TEXTURE_2D);
6948 glColor4f(.7, .35, 0, .5);
6950 glEnable(GL_LIGHTING);
6953 if (Tutorial::active && id != 0) {
6954 glColor4f(.7, .7, .7, 0.6);
6956 glEnable(GL_LIGHTING);
6958 if (canattack && cananger) {
6959 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6960 glDisable(GL_TEXTURE_2D);
6961 glColor4f(1, 0, 0, 0.8);
6964 glMatrixMode(GL_TEXTURE);
6966 glTranslatef(0, -smoketex, 0);
6967 glTranslatef(-smoketex, 0, 0);
6971 if (Tutorial::active && (id != 0)) {
6972 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6974 skeleton.drawmodel.draw();
6978 if (!playerdetail) {
6979 if (Tutorial::active && (id != 0)) {
6980 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6982 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6986 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed)) {
6987 if (Tutorial::active && id != 0) {
6989 glMatrixMode(GL_MODELVIEW);
6990 glEnable(GL_TEXTURE_2D);
6991 glColor4f(.7, .7, .7, 0.6);
6993 glEnable(GL_LIGHTING);
6995 if (canattack && cananger) {
6996 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6997 glDisable(GL_TEXTURE_2D);
6998 glColor4f(1, 0, 0, 0.8);
7001 glMatrixMode(GL_TEXTURE);
7003 glTranslatef(0, -smoketex * .6, 0);
7004 glTranslatef(smoketex * .6, 0, 0);
7007 if (Tutorial::active && (id != 0)) {
7008 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
7010 skeleton.drawmodel.draw();
7014 if (!playerdetail) {
7015 if (Tutorial::active && (id != 0)) {
7016 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
7018 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
7024 if (Tutorial::active && id != 0) {
7026 glMatrixMode(GL_MODELVIEW);
7027 glEnable(GL_TEXTURE_2D);
7029 if (skeleton.clothes) {
7033 skeleton.drawmodelclothes.draw();
7036 skeleton.drawmodelclothes.drawimmediate();
7043 if (num_weapons > 0) {
7044 for (k = 0; k < num_weapons; k++) {
7045 int i = weaponids[k];
7046 if (weaponactive == k) {
7047 if (weapons[i].getType() != staff) {
7048 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7049 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
7050 weaponattachmuscle = j;
7053 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7054 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) {
7055 weaponrotatemuscle = j;
7058 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
7059 if (creature == wolftype) {
7060 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
7063 if (weapons[i].getType() == staff) {
7064 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7065 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
7066 weaponattachmuscle = j;
7069 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7070 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) {
7071 weaponrotatemuscle = j;
7074 //weaponpoint=jointPos(rightwrist);
7075 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
7076 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
7077 XYZ tempnormthing, vec1, vec2;
7078 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
7079 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
7080 CrossProduct(&vec1, &vec2, &tempnormthing);
7081 Normalise(&tempnormthing);
7082 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim) {
7083 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
7087 if (weaponactive != k && weaponstuck != k) {
7088 if (weapons[i].getType() == knife) {
7089 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
7091 if (weapons[i].getType() == sword) {
7092 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
7094 if (weapons[i].getType() == staff) {
7095 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
7097 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7098 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) {
7099 weaponrotatemuscle = j;
7103 if (weaponstuck == k) {
7104 if (weaponstuckwhere == 0) {
7105 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
7107 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
7109 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7110 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) {
7111 weaponrotatemuscle = j;
7115 if (skeleton.free) {
7116 weapons[i].position = weaponpoint * scale + coords;
7117 weapons[i].bigrotation = 0;
7118 weapons[i].bigtilt = 0;
7119 weapons[i].bigtilt2 = 0;
7121 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;
7122 weapons[i].bigrotation = yaw;
7123 weapons[i].bigtilt = tilt;
7124 weapons[i].bigtilt2 = tilt2;
7126 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
7127 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
7128 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
7129 if (weaponactive == k) {
7130 if (weapons[i].getType() == knife) {
7131 weapons[i].smallrotation = 180;
7132 weapons[i].smallrotation2 = 0;
7133 if (isCrouch() || wasCrouch()) {
7134 weapons[i].smallrotation2 = 20;
7136 if (animTarget == hurtidleanim) {
7137 weapons[i].smallrotation2 = 50;
7139 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
7140 XYZ temppoint1, temppoint2;
7143 temppoint1 = jointPos(righthand);
7144 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7145 distance = findDistance(&temppoint1, &temppoint2);
7146 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7147 weapons[i].rotation2 *= 360 / 6.28;
7150 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7151 weapons[i].rotation1 *= 360 / 6.28;
7152 weapons[i].rotation3 = 0;
7153 weapons[i].smallrotation = -90;
7154 weapons[i].smallrotation2 = 0;
7155 if (temppoint1.x > temppoint2.x) {
7156 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7159 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
7160 XYZ temppoint1, temppoint2;
7163 temppoint1 = jointPos(righthand);
7164 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7165 distance = findDistance(&temppoint1, &temppoint2);
7166 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7167 weapons[i].rotation2 *= 360 / 6.28;
7170 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7171 weapons[i].rotation1 *= 360 / 6.28;
7172 weapons[i].rotation3 = 0;
7173 weapons[i].smallrotation = 90;
7174 weapons[i].smallrotation2 = 0;
7175 if (temppoint1.x > temppoint2.x) {
7176 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7179 if (animTarget == knifethrowanim) {
7180 weapons[i].smallrotation = 90;
7181 //weapons[i].smallrotation2=-90;
7182 weapons[i].smallrotation2 = 0;
7183 weapons[i].rotation1 = 0;
7184 weapons[i].rotation2 = 0;
7185 weapons[i].rotation3 = 0;
7187 if (animTarget == knifesneakattackanim && frameTarget < 5) {
7188 weapons[i].smallrotation = -90;
7189 weapons[i].rotation1 = 0;
7190 weapons[i].rotation2 = 0;
7191 weapons[i].rotation3 = 0;
7194 if (weapons[i].getType() == sword) {
7195 weapons[i].smallrotation = 0;
7196 weapons[i].smallrotation2 = 0;
7197 if (animTarget == knifethrowanim) {
7198 weapons[i].smallrotation = -90;
7199 weapons[i].smallrotation2 = 0;
7200 weapons[i].rotation1 = 0;
7201 weapons[i].rotation2 = 0;
7202 weapons[i].rotation3 = 0;
7204 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)) {
7205 XYZ temppoint1, temppoint2;
7208 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
7209 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7210 distance = findDistance(&temppoint1, &temppoint2);
7211 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7212 weapons[i].rotation2 *= 360 / 6.28;
7215 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7216 weapons[i].rotation1 *= 360 / 6.28;
7217 weapons[i].rotation3 = 0;
7218 weapons[i].smallrotation = 90;
7219 weapons[i].smallrotation2 = 0;
7220 if (temppoint1.x > temppoint2.x) {
7221 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7225 if (weapons[i].getType() == staff) {
7226 weapons[i].smallrotation = 100;
7227 weapons[i].smallrotation2 = 0;
7228 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
7229 XYZ temppoint1, temppoint2;
7232 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
7233 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7234 distance = findDistance(&temppoint1, &temppoint2);
7235 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7236 weapons[i].rotation2 *= 360 / 6.28;
7239 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7240 weapons[i].rotation1 *= 360 / 6.28;
7241 weapons[i].rotation3 = 0;
7242 weapons[i].smallrotation = 90;
7243 weapons[i].smallrotation2 = 0;
7244 if (temppoint1.x > temppoint2.x) {
7245 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7250 if (weaponactive != k && weaponstuck != k) {
7251 if (weapons[i].getType() == knife) {
7252 weapons[i].smallrotation = -70;
7253 weapons[i].smallrotation2 = 10;
7255 if (weapons[i].getType() == sword) {
7256 weapons[i].smallrotation = -100;
7257 weapons[i].smallrotation2 = -8;
7259 if (weapons[i].getType() == staff) {
7260 weapons[i].smallrotation = -100;
7261 weapons[i].smallrotation2 = -8;
7264 if (weaponstuck == k) {
7265 if (weaponstuckwhere == 0) {
7266 weapons[i].smallrotation = 180;
7268 weapons[i].smallrotation = 0;
7270 weapons[i].smallrotation2 = 10;
7277 if (skeleton.free) {
7280 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump()) {
7283 if (animCurrent != animTarget) {
7286 if (skeleton.free == 2) {
7295 int Person::SphereCheck(XYZ* p1, float radius, XYZ* p, XYZ* move, float* rotate, Model* model)
7297 static float distance;
7298 static float olddistance;
7299 static int intersecting;
7300 static int firstintersecting;
7303 static XYZ start, end;
7304 static float slopethreshold = -.4;
7306 firstintersecting = -1;
7310 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius) {
7314 *p1 = DoRotation(*p1, 0, -*rotate, 0);
7316 for (int i = 0; i < 4; i++) {
7317 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7318 if (model->Triangles[j].facenormal.y <= slopethreshold) {
7320 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)));
7321 if (distance < radius) {
7322 point = *p1 - model->Triangles[j].facenormal * distance;
7323 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]])) {
7326 if (!intersecting) {
7327 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7328 &model->vertex[model->Triangles[j].vertex[1]],
7331 if (!intersecting) {
7332 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
7333 &model->vertex[model->Triangles[j].vertex[2]],
7336 if (!intersecting) {
7337 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7338 &model->vertex[model->Triangles[j].vertex[2]],
7342 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7346 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)) {
7347 p1->y = point.y + radius;
7348 if ((animTarget == jumpdownanim || isFlip())) {
7349 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4)) {
7353 if (animTarget == jumpupanim) {
7355 animTarget = getIdle();
7362 pause_sound(whooshsound);
7363 OPENAL_SetVolume(channels[whooshsound], 0);
7366 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
7370 animTarget = getLanding();
7371 emit_sound_at(landsound, coords, 128.);
7374 addEnvSound(coords);
7381 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7382 olddistance = distance;
7383 firstintersecting = j;
7388 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7389 if (model->Triangles[j].facenormal.y > slopethreshold) {
7392 start.y -= radius / 4;
7393 XYZ& v0 = model->vertex[model->Triangles[j].vertex[0]];
7394 XYZ& v1 = model->vertex[model->Triangles[j].vertex[1]];
7395 XYZ& v2 = model->vertex[model->Triangles[j].vertex[2]];
7396 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)));
7397 if (distance < radius * .5) {
7398 point = start - model->Triangles[j].facenormal * distance;
7399 if (PointInTriangle(&point, model->Triangles[j].facenormal, &v0, &v1, &v2)) {
7402 if (!intersecting) {
7403 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
7405 if (!intersecting) {
7406 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7408 if (!intersecting) {
7409 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7412 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7413 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
7415 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;
7416 if (findLengthfast(&start) < findLengthfast(&velocity)) {
7420 *p1 += model->Triangles[j].facenormal * (distance - radius * .5);
7423 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7424 olddistance = distance;
7425 firstintersecting = j;
7432 *p = DoRotation(*p, 0, *rotate, 0);
7436 *p1 = DoRotation(*p1, 0, *rotate, 0);
7439 return firstintersecting;
7442 int findPathDist(int start, int end)
7447 unsigned int smallestcount = 1000;
7448 for (char i = 0; i < 50; i++) {
7449 unsigned int count = 0;
7454 while (last != end && count < 30) {
7456 for (int j = 0; j < Game::numpathpoints; j++) {
7457 if (j != last && j != last2 && j != last3 && j != last4) {
7459 if (Game::numpathpointconnect[j]) {
7460 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7461 if (Game::pathpointconnect[j][k] == last) {
7467 if (Game::numpathpointconnect[last]) {
7468 for (int k = 0; k < Game::numpathpointconnect[last]; k++) {
7469 if (Game::pathpointconnect[last][k] == j) {
7476 if (closest == -1 || Random() % 2 == 0) {
7488 if (count < smallestcount) {
7489 smallestcount = count;
7492 return smallestcount;
7495 void Person::takeWeapon(int weaponId)
7498 weapons[weaponId].owner = id;
7499 if (num_weapons > 0) {
7500 weaponids[num_weapons] = weaponids[0];
7503 weaponids[0] = weaponId;
7506 void Person::addClothes()
7508 if (numclothes > 0) {
7509 for (int i = 0; i < numclothes; i++) {
7516 bool Person::addClothes(const int& clothesId)
7519 const std::string fileName = clothes[clothesId];
7521 GLubyte* array = &skeleton.skinText[0];
7525 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
7530 float tintr = clothestintr[clothesId];
7531 float tintg = clothestintg[clothesId];
7532 float tintb = clothestintb[clothesId];
7554 int bytesPerPixel = texture.bpp / 8;
7558 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
7559 if (bytesPerPixel == 3) {
7561 } else if ((i + 1) % 4 == 0) {
7562 alphanum = texture.data[i];
7564 if ((i + 1) % 4 || bytesPerPixel == 3) {
7566 texture.data[i] *= tintr;
7569 texture.data[i] *= tintg;
7572 texture.data[i] *= tintb;
7574 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
7586 if (aitype != playercontrolled && !Dialog::inDialog()) {
7588 //disable movement in editor
7589 if (Game::editorenabled) {
7594 if (distsqflat(&Person::players[0]->coords, &coords) < 30 &&
7595 Person::players[0]->coords.y > coords.y + 2 &&
7596 !Person::players[0]->onterrain) {
7601 if (aitype == pathfindtype) {
7602 if (finalpathfindpoint == -1) {
7603 float closestdistance;
7604 float tempdist = 0.0f;
7608 closestdistance = -1;
7609 for (int j = 0; j < Game::numpathpoints; j++) {
7610 if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) {
7611 closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]);
7613 finaltarget = Game::pathpoint[j];
7616 finalpathfindpoint = closest;
7617 for (int j = 0; j < Game::numpathpoints; j++) {
7618 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7619 DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7620 if (sq(tempdist) < closestdistance) {
7621 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7622 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7623 closestdistance = sq(tempdist);
7625 finaltarget = colpoint;
7630 finalpathfindpoint = closest;
7632 if (targetpathfindpoint == -1) {
7633 float closestdistance;
7634 float tempdist = 0.0f;
7638 closestdistance = -1;
7639 if (lastpathfindpoint == -1) {
7640 for (int j = 0; j < Game::numpathpoints; j++) {
7641 if (j != lastpathfindpoint) {
7642 if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) {
7643 closestdistance = distsq(&coords, &Game::pathpoint[j]);
7648 targetpathfindpoint = closest;
7649 for (int j = 0; j < Game::numpathpoints; j++) {
7650 if (j != lastpathfindpoint) {
7651 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7652 DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7653 if (sq(tempdist) < closestdistance) {
7654 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7655 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7656 closestdistance = sq(tempdist);
7663 targetpathfindpoint = closest;
7665 for (int j = 0; j < Game::numpathpoints; j++) {
7666 if (j != lastpathfindpoint &&
7667 j != lastpathfindpoint2 &&
7668 j != lastpathfindpoint3 &&
7669 j != lastpathfindpoint4) {
7671 if (Game::numpathpointconnect[j]) {
7672 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7673 if (Game::pathpointconnect[j][k] == lastpathfindpoint) {
7679 if (Game::numpathpointconnect[lastpathfindpoint]) {
7680 for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++) {
7681 if (Game::pathpointconnect[lastpathfindpoint][k] == j) {
7688 tempdist = findPathDist(j, finalpathfindpoint);
7689 if (closest == -1 || tempdist < closestdistance) {
7690 closestdistance = tempdist;
7696 targetpathfindpoint = closest;
7699 losupdatedelay -= multiplier;
7701 targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]);
7702 lookyaw = targetyaw;
7704 //reached target point
7705 if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) {
7706 lastpathfindpoint4 = lastpathfindpoint3;
7707 lastpathfindpoint3 = lastpathfindpoint2;
7708 lastpathfindpoint2 = lastpathfindpoint;
7709 lastpathfindpoint = targetpathfindpoint;
7710 if (lastpathfindpoint2 == -1) {
7711 lastpathfindpoint2 = lastpathfindpoint;
7713 if (lastpathfindpoint3 == -1) {
7714 lastpathfindpoint3 = lastpathfindpoint2;
7716 if (lastpathfindpoint4 == -1) {
7717 lastpathfindpoint4 = lastpathfindpoint3;
7719 targetpathfindpoint = -1;
7721 if (distsqflat(&coords, &finalfinaltarget) <
7722 distsqflat(&coords, &finaltarget) ||
7723 distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) ||
7724 lastpathfindpoint == finalpathfindpoint) {
7725 aitype = passivetype;
7736 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7737 targetyaw += 90 * (whichdirection * 2 - 1);
7740 if (collided < 1 || animTarget != jumpupanim) {
7743 if ((collided > .8 && jumppower >= 5)) {
7747 if ((!Tutorial::active || cananger) &&
7749 !Person::players[0]->dead &&
7750 distsq(&coords, &Person::players[0]->coords) < 400 &&
7752 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7753 Animation::animations[Person::players[0]->animTarget].height != lowheight &&
7754 !Game::editorenabled &&
7755 (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain)) {
7756 aitype = attacktypecutoff;
7758 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7759 Animation::animations[Person::players[0]->animTarget].height == highheight &&
7760 !Game::editorenabled) {
7761 aitype = attacktypecutoff;
7764 if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7765 losupdatedelay = .2;
7766 for (unsigned j = 0; j < Person::players.size(); j++) {
7767 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7768 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7769 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7770 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7771 if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain) {
7772 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) ||
7773 (Person::players[j]->animTarget == hanganim &&
7774 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7775 aitype = searchtype;
7777 lastseen = Person::players[j]->coords;
7788 if (aitype == attacktypecutoff && Game::musictype != 2) {
7789 if (creature != wolftype) {
7796 if (aitype != passivetype && Game::leveltime > .5) {
7797 howactive = typeactive;
7800 if (aitype == passivetype) {
7801 aiupdatedelay -= multiplier;
7802 losupdatedelay -= multiplier;
7803 lastseentime += multiplier;
7804 pausetime -= multiplier;
7805 if (lastseentime > 1) {
7809 if (aiupdatedelay < 0) {
7810 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7811 targetyaw = roughDirectionTo(coords, waypoints[waypoint]);
7812 lookyaw = targetyaw;
7813 aiupdatedelay = .05;
7815 if (distsqflat(&coords, &waypoints[waypoint]) < 1) {
7816 if (waypointtype[waypoint] == wppause) {
7820 if (waypoint > numwaypoints - 1) {
7826 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7838 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7839 if (!avoidsomething) {
7840 targetyaw += 90 * (whichdirection * 2 - 1);
7842 XYZ leftpos, rightpos;
7843 float leftdist, rightdist;
7844 leftpos = coords + DoRotation(facing, 0, 90, 0);
7845 rightpos = coords - DoRotation(facing, 0, 90, 0);
7846 leftdist = distsq(&leftpos, &avoidwhere);
7847 rightdist = distsq(&rightpos, &avoidwhere);
7848 if (leftdist < rightdist) {
7856 if (collided < 1 || animTarget != jumpupanim) {
7859 if ((collided > .8 && jumppower >= 5)) {
7864 if (!Game::editorenabled) {
7865 if (howactive <= typesleeping) {
7866 if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile) {
7867 for (int j = 0; j < numenvsounds; j++) {
7868 float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
7869 if (vol > 0 && distsq(&coords, &envsound[j]) < 2 * (vol + vol * (creature == rabbittype) * 3)) {
7870 aitype = attacktypecutoff;
7876 if (aitype != passivetype) {
7877 if (howactive == typesleeping) {
7878 setTargetAnimation(getupfromfrontanim);
7880 howactive = typeactive;
7884 if (howactive < typesleeping &&
7885 ((!Tutorial::active || cananger) && hostile) &&
7886 !Person::players[0]->dead &&
7887 distsq(&coords, &Person::players[0]->coords) < 400 &&
7889 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7890 Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled) {
7891 aitype = attacktypecutoff;
7893 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7894 Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled) {
7895 aitype = attacktypecutoff;
7899 if (creature == wolftype) {
7901 for (unsigned j = 0; j < Person::players.size(); j++) {
7902 if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
7903 float smelldistance = 50;
7904 if (j == 0 && Person::players[j]->num_weapons > 0) {
7905 if (weapons[Person::players[j]->weaponids[0]].bloody) {
7906 smelldistance = 100;
7908 if (Person::players[j]->num_weapons == 2) {
7909 if (weapons[Person::players[j]->weaponids[1]].bloody) {
7910 smelldistance = 100;
7915 smelldistance = 100;
7917 windsmell = windvector;
7918 Normalise(&windsmell);
7919 windsmell = windsmell * 2 + Person::players[j]->coords;
7920 if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled) {
7921 aitype = attacktypecutoff;
7927 if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7928 losupdatedelay = .2;
7929 for (unsigned j = 0; j < Person::players.size(); j++) {
7930 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7931 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7932 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7933 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7934 if ((-1 == Object::checkcollide(
7935 DoRotation(jointPos(head), 0, yaw, 0) *
7938 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0) *
7939 Person::players[j]->scale +
7940 Person::players[j]->coords) &&
7941 !Person::players[j]->isWallJump()) ||
7942 (Person::players[j]->animTarget == hanganim &&
7943 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7945 if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight) {
7954 if (lastseentime <= 0) {
7955 aitype = searchtype;
7957 lastseen = Person::players[j]->coords;
7965 if (aitype == attacktypecutoff && Game::musictype != 2) {
7966 if (creature != wolftype) {
7970 if (creature == wolftype) {
7980 if (aitype == searchtype) {
7981 aiupdatedelay -= multiplier;
7982 losupdatedelay -= multiplier;
7984 lastseentime -= multiplier;
7986 lastchecktime -= multiplier;
7988 if (isRun() && !onground) {
7989 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7990 XYZ test2 = coords + facing;
7992 XYZ test = coords + facing;
7994 j = Object::checkcollide(test2, test, laststanding);
7996 j = Object::checkcollide(test2, test);
8000 setTargetAnimation(getStop());
8003 //aitype=passivetype;
8004 aitype = pathfindtype;
8005 finalfinaltarget = waypoints[waypoint];
8006 finalpathfindpoint = -1;
8007 targetpathfindpoint = -1;
8008 lastpathfindpoint = -1;
8009 lastpathfindpoint2 = -1;
8010 lastpathfindpoint3 = -1;
8011 lastpathfindpoint4 = -1;
8017 //check out last seen location
8018 if (aiupdatedelay < 0) {
8019 targetyaw = roughDirectionTo(coords, lastseen);
8020 lookyaw = targetyaw;
8021 aiupdatedelay = .05;
8024 if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) {
8027 lastseen.x += (float(Random() % 100) - 50) / 25;
8028 lastseen.z += (float(Random() % 100) - 50) / 25;
8039 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8040 if (!avoidsomething) {
8041 targetyaw += 90 * (whichdirection * 2 - 1);
8043 XYZ leftpos, rightpos;
8044 float leftdist, rightdist;
8045 leftpos = coords + DoRotation(facing, 0, 90, 0);
8046 rightpos = coords - DoRotation(facing, 0, 90, 0);
8047 leftdist = distsq(&leftpos, &avoidwhere);
8048 rightdist = distsq(&rightpos, &avoidwhere);
8049 if (leftdist < rightdist) {
8057 if (collided < 1 || animTarget != jumpupanim) {
8060 if ((collided > .8 && jumppower >= 5)) {
8064 if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile)) {
8065 for (int k = 0; k < numenvsounds; k++) {
8066 if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) {
8067 aitype = attacktypecutoff;
8072 if (!Person::players[0]->dead &&
8073 losupdatedelay < 0 &&
8074 !Game::editorenabled &&
8076 ((!Tutorial::active || cananger) && hostile)) {
8077 losupdatedelay = .2;
8078 if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) {
8079 aitype = attacktypecutoff;
8082 if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight) {
8083 //TODO: factor out canSeePlayer()
8084 if (distsq(&coords, &Person::players[0]->coords) < 400) {
8085 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
8086 if ((Object::checkcollide(
8087 DoRotation(jointPos(head), 0, yaw, 0) *
8090 DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0) *
8091 Person::players[0]->scale +
8092 Person::players[0]->coords) == -1) ||
8093 (Person::players[0]->animTarget == hanganim && normaldotproduct(Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) {
8094 /* //TODO: changed j to 0 on a whim, make sure this is correct
8095 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
8096 Person::players[j]->facing,coords-Person::players[j]->coords)<0)
8098 aitype = attacktypecutoff;
8106 if (lastseentime < 0) {
8107 //aitype=passivetype;
8109 aitype = pathfindtype;
8110 finalfinaltarget = waypoints[waypoint];
8111 finalpathfindpoint = -1;
8112 targetpathfindpoint = -1;
8113 lastpathfindpoint = -1;
8114 lastpathfindpoint2 = -1;
8115 lastpathfindpoint3 = -1;
8116 lastpathfindpoint4 = -1;
8120 if (aitype != gethelptype) {
8124 //get help from buddies
8125 if (aitype == gethelptype) {
8126 runninghowlong += multiplier;
8127 aiupdatedelay -= multiplier;
8129 if (aiupdatedelay < 0 || ally == 0) {
8133 //TODO: factor out closest search somehow
8136 float closestdist = -1;
8137 for (unsigned k = 0; k < Person::players.size(); k++) {
8138 if ((k != id) && (k != 0) && !Person::players[k]->dead &&
8139 (Person::players[k]->howactive < typedead1) &&
8140 !Person::players[k]->skeleton.free &&
8141 (Person::players[k]->aitype == passivetype)) {
8142 float distance = distsq(&coords, &Person::players[k]->coords);
8143 if (closestdist == -1 || distance < closestdist) {
8144 closestdist = distance;
8149 if (closest != -1) {
8154 lastseen = Person::players[0]->coords;
8160 XYZ facing = coords;
8161 XYZ flatfacing = Person::players[ally]->coords;
8162 facing.y += jointPos(head).y * scale;
8163 flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale;
8164 if (-1 != Object::checkcollide(facing, flatfacing)) {
8168 //no available ally, run back to player
8170 Person::players[ally]->skeleton.free ||
8171 Person::players[ally]->aitype != passivetype ||
8172 lastseentime <= 0) {
8173 aitype = searchtype;
8179 targetyaw = roughDirectionTo(coords, Person::players[ally]->coords);
8180 lookyaw = targetyaw;
8181 aiupdatedelay = .05;
8184 if (distsqflat(&coords, &Person::players[ally]->coords) < 3) {
8185 aitype = searchtype;
8187 Person::players[ally]->aitype = searchtype;
8188 if (Person::players[ally]->lastseentime < lastseentime) {
8189 Person::players[ally]->lastseen = lastseen;
8190 Person::players[ally]->lastseentime = lastseentime;
8191 Person::players[ally]->lastchecktime = lastchecktime;
8195 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8196 if (!avoidsomething) {
8197 targetyaw += 90 * (whichdirection * 2 - 1);
8199 XYZ leftpos, rightpos;
8200 float leftdist, rightdist;
8201 leftpos = coords + DoRotation(facing, 0, 90, 0);
8202 rightpos = coords - DoRotation(facing, 0, 90, 0);
8203 leftdist = distsq(&leftpos, &avoidwhere);
8204 rightdist = distsq(&rightpos, &avoidwhere);
8205 if (leftdist < rightdist) {
8220 if (collided < 1 || animTarget != jumpupanim) {
8223 if (collided > .8 && jumppower >= 5) {
8228 //retreiving a weapon on the ground
8229 if (aitype == getweapontype) {
8230 aiupdatedelay -= multiplier;
8231 lastchecktime -= multiplier;
8233 if (aiupdatedelay < 0) {
8239 float closestdist = -1;
8240 for (unsigned k = 0; k < weapons.size(); k++) {
8241 if (weapons[k].owner == -1) {
8242 float distance = distsq(&coords, &weapons[k].position);
8243 if (closestdist == -1 || distance < closestdist) {
8244 closestdist = distance;
8249 if (closest != -1) {
8258 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile)) {
8259 if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) {
8260 aitype = attacktypecutoff;
8264 if (!Person::players[0]->dead) {
8266 if (weapons[ally].owner != -1 ||
8267 distsq(&coords, &weapons[ally].position) > 16) {
8268 aitype = attacktypecutoff;
8271 //TODO: factor these out as moveToward()
8272 targetyaw = roughDirectionTo(coords, weapons[ally].position);
8273 lookyaw = targetyaw;
8274 aiupdatedelay = .05;
8277 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8278 if (!avoidsomething) {
8279 targetyaw += 90 * (whichdirection * 2 - 1);
8281 XYZ leftpos, rightpos;
8282 float leftdist, rightdist;
8283 leftpos = coords + DoRotation(facing, 0, 90, 0);
8284 rightpos = coords - DoRotation(facing, 0, 90, 0);
8285 leftdist = distsq(&leftpos, &avoidwhere);
8286 rightdist = distsq(&rightpos, &avoidwhere);
8287 if (leftdist < rightdist) {
8303 if (animTarget != crouchremoveknifeanim &&
8304 animTarget != removeknifeanim) {
8305 throwtogglekeydown = 0;
8309 if (collided < 1 || animTarget != jumpupanim) {
8312 if ((collided > .8 && jumppower >= 5)) {
8317 if (aitype == attacktypecutoff) {
8318 aiupdatedelay -= multiplier;
8319 //dodge or reverse rabbit kicks, knife throws, flips
8320 if (damage < damagetolerance * 2 / 3) {
8321 if ((Person::players[0]->animTarget == rabbitkickanim ||
8322 Person::players[0]->animTarget == knifethrowanim ||
8323 (Person::players[0]->isFlip() &&
8324 normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) &&
8325 !Person::players[0]->skeleton.free &&
8326 (aiupdatedelay < .1)) {
8331 if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
8332 if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
8333 if (isIdle() || isCrouch() || isRun() || isFlip()) {
8334 if (abs(Random() % 2) == 0) {
8335 setTargetAnimation(backhandspringanim);
8337 setTargetAnimation(rollanim);
8339 targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
8342 if (animTarget == jumpupanim || animTarget == jumpdownanim) {
8343 setTargetAnimation(flipanim);
8348 aiupdatedelay = .02;
8351 //get confused by flips
8352 if (Person::players[0]->isFlip() &&
8353 !Person::players[0]->skeleton.free &&
8354 Person::players[0]->animTarget != walljumprightkickanim &&
8355 Person::players[0]->animTarget != walljumpleftkickanim) {
8356 if (distsq(&Person::players[0]->coords, &coords) < 25) {
8357 if ((1 - damage / damagetolerance) > .5) {
8362 //go for weapon on the ground
8363 if (wentforweapon < 3) {
8364 for (unsigned k = 0; k < weapons.size(); k++) {
8365 if (creature != wolftype) {
8366 if (num_weapons == 0 &&
8367 weapons[k].owner == -1 &&
8368 weapons[k].velocity.x == 0 &&
8369 weapons[k].velocity.z == 0 &&
8370 weapons[k].velocity.y == 0) {
8371 if (distsq(&coords, &weapons[k].position) < 16) {
8374 aitype = getweapontype;
8381 //dodge/reverse walljump kicks
8382 if (damage < damagetolerance / 2) {
8383 if (Animation::animations[animTarget].height != highheight) {
8384 if (damage < damagetolerance * .5 &&
8385 ((Person::players[0]->animTarget == walljumprightkickanim ||
8386 Person::players[0]->animTarget == walljumpleftkickanim) &&
8387 ((aiupdatedelay < .15 &&
8389 (aiupdatedelay < .08 &&
8390 difficulty != 2)))) {
8395 //walked off a ledge (?)
8396 if (isRun() && !onground) {
8397 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
8398 XYZ test2 = coords + facing;
8400 XYZ test = coords + facing;
8402 j = Object::checkcollide(test2, test, laststanding);
8404 j = Object::checkcollide(test2, test);
8408 setTargetAnimation(getStop());
8411 aitype = pathfindtype;
8412 finalfinaltarget = waypoints[waypoint];
8413 finalpathfindpoint = -1;
8414 targetpathfindpoint = -1;
8415 lastpathfindpoint = -1;
8416 lastpathfindpoint2 = -1;
8417 lastpathfindpoint3 = -1;
8418 lastpathfindpoint4 = -1;
8424 //lose sight of player in the air (?)
8425 if (Person::players[0]->coords.y > coords.y + 5 &&
8426 Animation::animations[Person::players[0]->animTarget].height != highheight &&
8427 !Person::players[0]->onterrain) {
8428 aitype = pathfindtype;
8429 finalfinaltarget = waypoints[waypoint];
8430 finalpathfindpoint = -1;
8431 targetpathfindpoint = -1;
8432 lastpathfindpoint = -1;
8433 lastpathfindpoint2 = -1;
8434 lastpathfindpoint3 = -1;
8435 lastpathfindpoint4 = -1;
8437 //it's time to think (?)
8438 if (aiupdatedelay < 0 &&
8439 !Animation::animations[animTarget].attack &&
8440 animTarget != staggerbackhighanim &&
8441 animTarget != staggerbackhardanim &&
8442 animTarget != backhandspringanim &&
8443 animTarget != dodgebackanim) {
8445 if (weaponactive == -1 && num_weapons > 0) {
8446 drawkeydown = Random() % 2;
8450 rabbitkickenabled = Random() % 2;
8452 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
8453 XYZ targetpoint = Person::players[0]->coords;
8454 float vellength = findLength(&velocity);
8455 if (vellength != 0 &&
8456 distsq(&Person::players[0]->coords, &coords) < distsq(&rotatetarget, &coords)) {
8457 targetpoint += Person::players[0]->velocity *
8458 findDistance(&Person::players[0]->coords, &coords) / vellength;
8460 targetyaw = roughDirectionTo(coords, targetpoint);
8461 lookyaw = targetyaw;
8462 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
8464 if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1)) {
8466 } else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
8467 distsq(&coords, &Person::players[0]->coords) < 9) &&
8468 Person::players[0]->weaponactive != -1) {
8470 } else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0)) {
8475 //chill out around the corpse
8476 if (Person::players[0]->dead) {
8478 if (Random() % 10 == 0) {
8481 if (Random() % 100 == 0) {
8482 aitype = pathfindtype;
8483 finalfinaltarget = waypoints[waypoint];
8484 finalpathfindpoint = -1;
8485 targetpathfindpoint = -1;
8486 lastpathfindpoint = -1;
8487 lastpathfindpoint2 = -1;
8488 lastpathfindpoint3 = -1;
8489 lastpathfindpoint4 = -1;
8498 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8499 targetyaw += 90 * (whichdirection * 2 - 1);
8502 if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype) {
8507 if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7) {
8512 if (aitype != playercontrolled &&
8517 for (unsigned j = 0; j < Person::players.size(); j++) {
8518 if (j != id && !Person::players[j]->skeleton.free &&
8519 Person::players[j]->hasvictim &&
8520 (Tutorial::active && reversaltrain ||
8521 Random() % 2 == 0 && difficulty == 2 ||
8522 Random() % 4 == 0 && difficulty == 1 ||
8523 Random() % 8 == 0 && difficulty == 0 ||
8524 Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
8525 Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
8526 (Random() % 2 == 0 || difficulty == 2) ||
8527 (isIdle() || isRun()) &&
8528 Person::players[j]->weaponactive != -1 ||
8529 Person::players[j]->animTarget == swordslashanim &&
8530 weaponactive != -1 ||
8531 Person::players[j]->animTarget == staffhitanim ||
8532 Person::players[j]->animTarget == staffspinhitanim)) {
8533 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
8534 Person::players[j]->victim == Person::players[id] &&
8535 (Person::players[j]->animTarget == sweepanim ||
8536 Person::players[j]->animTarget == spinkickanim ||
8537 Person::players[j]->animTarget == staffhitanim ||
8538 Person::players[j]->animTarget == staffspinhitanim ||
8539 Person::players[j]->animTarget == winduppunchanim ||
8540 Person::players[j]->animTarget == upunchanim ||
8541 Person::players[j]->animTarget == wolfslapanim ||
8542 Person::players[j]->animTarget == knifeslashstartanim ||
8543 Person::players[j]->animTarget == swordslashanim &&
8544 (distsq(&Person::players[j]->coords, &coords) < 2 ||
8545 weaponactive != -1))) {
8555 Person::players[target]->Reverse();
8562 if (collided > .8 && jumppower >= 5 ||
8563 distsq(&coords, &Person::players[0]->coords) > 400 &&
8565 creature == rabbittype) {
8568 //TODO: why are we controlling the human?
8569 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
8570 Person::players[0]->jumpkeydown = 0;
8572 if (Person::players[0]->animTarget == jumpdownanim &&
8573 distsq(&Person::players[0]->coords, &coords) < 40) {
8580 if (Tutorial::active) {
8586 XYZ facing = coords;
8587 XYZ flatfacing = Person::players[0]->coords;
8588 facing.y += jointPos(head).y * scale;
8589 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
8590 if (occluded >= 2) {
8591 if (-1 != Object::checkcollide(facing, flatfacing)) {
8595 if (lastseentime <= 0 &&
8596 (creature != wolftype ||
8597 weaponstuck == -1)) {
8598 aitype = searchtype;
8600 lastseen = Person::players[0]->coords;
8609 if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
8610 (aitype == attacktypecutoff ||
8611 aitype == searchtype)) {
8612 if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
8613 XYZ test = Person::players[0]->coords;
8615 if (-1 == Object::checkcollide(Person::players[0]->coords, test)) {
8621 if (aitype == passivetype && !(numwaypoints > 1) ||
8623 pause && damage > superpermanentdamage) {
8642 XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0);
8643 facing = flatfacing;
8645 if (aitype == attacktypecutoff) {
8646 targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
8647 targetheadpitch = pitchTo(coords, Person::players[0]->coords);
8648 } else if (howactive >= typesleeping) {
8649 targetheadyaw = targetyaw;
8650 targetheadpitch = 0;
8652 if (interestdelay <= 0) {
8653 interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
8654 headtarget = coords;
8655 headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
8656 headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
8657 headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
8658 headtarget += facing * 1.5;
8660 targetheadyaw = 180 - roughDirectionTo(coords, headtarget);
8661 targetheadpitch = pitchTo(coords, headtarget);