2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2017 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
21 #include "Objects/Person.hpp"
23 #include "Animation/Animation.hpp"
24 #include "Audio/Sounds.hpp"
25 #include "Audio/openal_wrapper.hpp"
27 #include "Level/Awards.hpp"
28 #include "Level/Dialog.hpp"
29 #include "Tutorial.hpp"
30 #include "Utils/Folders.hpp"
32 extern float multiplier;
33 extern Terrain terrain;
35 extern int environment;
37 extern FRUSTUM frustum;
39 extern float realmultiplier;
41 extern float slomodelay;
42 extern bool cellophane;
43 extern float texdetail;
44 extern float realtexdetail;
45 extern int bloodtoggle;
46 extern bool autoslomo;
47 extern float camerashake;
49 extern float viewdistance;
50 extern float blackout;
51 extern int difficulty;
52 extern bool decalstoggle;
53 extern float fadestart;
55 extern bool winfreeze;
56 extern bool showpoints;
57 extern bool immediate;
58 extern float smoketex;
59 extern bool reversaltrain;
60 extern bool canattack;
62 extern float damagedealt;
64 extern float hostiletime;
66 extern bool gamestarted;
68 extern XYZ envsound[30];
69 extern float envsoundvol[30];
70 extern int numenvsounds;
71 extern float envsoundlife[30];
73 extern XYZ windvector;
75 std::vector<std::shared_ptr<Person>> Person::players;
80 , animCurrent(bounceidleanim)
81 , animTarget(bounceidleanim)
88 , howactive(typeactive)
90 , superruntoggle(false)
124 , rabbitkickenabled(false)
137 , superpermanentdamage(0)
175 , normalsupdatedelay(0)
179 , forwardkeydown(false)
180 , forwardstogglekeydown(false)
181 , rightkeydown(false)
185 , jumptogglekeydown(false)
186 , crouchkeydown(false)
187 , crouchtogglekeydown(false)
189 , drawtogglekeydown(false)
190 , throwkeydown(false)
191 , throwtogglekeydown(false)
192 , attackkeydown(false)
214 , whichdirection(false)
215 , whichdirectiondelay(0)
216 , avoidsomething(false)
226 , lefthandmorphness(0)
227 , righthandmorphness(0)
231 , targetlefthandmorphness(0)
232 , targetrighthandmorphness(0)
233 , targetheadmorphness(1)
234 , targetchestmorphness(0)
235 , targettailmorphness(0)
236 , lefthandmorphstart(0)
237 , lefthandmorphend(0)
238 , righthandmorphstart(0)
239 , righthandmorphend(0)
249 , highreversaldelay(0)
250 , lowreversaldelay(0)
299 , weaponstuckwhere(0)
312 , finalpathfindpoint(0)
313 , targetpathfindpoint(0)
314 , lastpathfindpoint(0)
315 , lastpathfindpoint2(0)
316 , lastpathfindpoint3(0)
317 , lastpathfindpoint4(0)
337 , neckspurtparticledelay(0)
342 , rabbitkickragdoll(false)
350 damagetolerance = PersonType::types[creature].defaultDamageTolerance;
351 setProportions(1, 1, 1, 1);
354 /* Read a person in tfile. Throws an error if it’s not valid */
355 Person::Person(FILE* tfile, int mapvers, unsigned i)
359 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
361 funpackf(tfile, "Bi", &howactive);
363 howactive = typeactive;
366 funpackf(tfile, "Bf", &scale);
371 funpackf(tfile, "Bb", &immobile);
376 funpackf(tfile, "Bf", &yaw);
381 if (num_weapons < 0 || num_weapons > 5) {
382 throw InvalidPersonException();
384 if (num_weapons > 0 && num_weapons < 5) {
385 for (int j = 0; j < num_weapons; j++) {
386 weaponids[j] = weapons.size();
388 funpackf(tfile, "Bi", &type);
389 weapons.push_back(Weapon(type, id));
392 funpackf(tfile, "Bi", &numwaypoints);
393 for (int j = 0; j < numwaypoints; j++) {
394 funpackf(tfile, "Bf", &waypoints[j].x);
395 funpackf(tfile, "Bf", &waypoints[j].y);
396 funpackf(tfile, "Bf", &waypoints[j].z);
398 funpackf(tfile, "Bi", &waypointtype[j]);
400 waypointtype[j] = wpkeepwalking;
404 funpackf(tfile, "Bi", &waypoint);
405 if (waypoint > (numwaypoints - 1)) {
409 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
410 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
411 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
412 funpackf(tfile, "Bf Bf", &power, &speedmult);
415 funpackf(tfile, "Bf Bf Bf Bf", &proportions[0], &proportions[1], &proportions[2], &proportions[3]);
417 setProportions(1, 1, 1, 1);
420 funpackf(tfile, "Bi", &numclothes);
421 for (int k = 0; k < numclothes; k++) {
423 funpackf(tfile, "Bi", &templength);
424 for (int l = 0; l < templength; l++) {
425 funpackf(tfile, "Bb", &clothes[k][l]);
427 clothes[k][templength] = '\0';
428 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
433 damagetolerance = PersonType::types[creature].defaultDamageTolerance;
436 scale = PersonType::types[creature].defaultScale;
440 realoldcoords = coords;
443 void Person::changeCreatureType(person_type type)
447 skeletonLoad(type == rabbittype);
448 scale = PersonType::types[creature].defaultScale;
449 damagetolerance = PersonType::types[creature].defaultDamageTolerance;
452 void Person::skeletonLoad(bool clothes)
456 PersonType::types[creature].figureFileName,
457 PersonType::types[creature].lowFigureFileName,
458 PersonType::types[creature].clothesFileName,
459 PersonType::types[creature].modelFileNames[0],
460 PersonType::types[creature].modelFileNames[1],
461 PersonType::types[creature].modelFileNames[2],
462 PersonType::types[creature].modelFileNames[3],
463 PersonType::types[creature].modelFileNames[4],
464 PersonType::types[creature].modelFileNames[5],
465 PersonType::types[creature].modelFileNames[6],
466 PersonType::types[creature].lowModelFileName,
467 PersonType::types[creature].modelClothesFileName,
470 skeleton.drawmodel.textureptr.load(PersonType::types[creature].skins[whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
473 void Person::setProportions(float head, float body, float arms, float legs)
475 proportions[0] = head;
476 proportions[1] = body;
477 proportions[2] = arms;
478 proportions[3] = legs;
481 float Person::getProportion(int part) const
483 return proportions[part];
486 XYZ Person::getProportionXYZ(int part) const
488 XYZ prop = PersonType::types[creature].proportions[part] * proportions[part];
498 * GameTick/doPlayerCollisions
500 void Person::CheckKick()
502 if (!(hasvictim && (animTarget == rabbitkickanim && victim && victim != this->shared_from_this() && frameCurrent >= 2 && animCurrent == rabbitkickanim) && distsq(&coords, &victim->coords) < 1.2 && !victim->skeleton.free)) {
506 if (Animation::animations[victim->animTarget].height != lowheight) {
507 float damagemult = PersonType::types[creature].power * power * power;
508 XYZ relative = velocity;
510 Normalise(&relative);
514 if (!Tutorial::active) {
515 emit_sound_at(heavyimpactsound, victim->coords);
518 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
519 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
522 victim->DoDamage(100 * damagemult / victim->protectionhigh);
529 animTarget = backflipanim;
531 velocity = facing * -10;
535 resume_stream(whooshsound);
538 award_bonus(id, cannon);
539 } else if (victim->isCrouch()) {
540 animTarget = rabbitkickreversedanim;
541 animCurrent = rabbitkickreversedanim;
542 victim->animCurrent = rabbitkickreversalanim;
543 victim->animTarget = rabbitkickreversalanim;
549 victim->oldcoords = victim->coords;
550 coords = victim->coords;
551 victim->targetyaw = targetyaw;
552 victim->victim = this->shared_from_this();
559 * GameTick::doPlayerCollisions - spread fire between players
560 * GameTick::ProcessDevKeys - press f to ignite
561 * Person::DoStuff - spread fire from lit campfires and bushes
563 void Person::CatchFire()
565 XYZ flatfacing, flatvelocity;
567 for (int i = 0; i < 10; i++) {
568 howmany = fabs(Random() % (skeleton.joints.size()));
570 flatvelocity = skeleton.joints[howmany].velocity;
571 flatfacing = skeleton.joints[howmany].position * scale + coords;
573 flatvelocity = velocity;
574 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
576 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
581 emit_sound_at(firestartsound, coords);
583 emit_stream_at(stream_firesound, coords);
591 * idle animation for this creature (depending on status)
593 int Person::getIdle()
595 if (Dialog::inDialog() && (howactive == typeactive) && PersonType::types[creature].hasAnimTalkIdle()) {
596 return PersonType::types[creature].animTalkIdle;
598 if (hasvictim && (victim != this->shared_from_this())) {
599 if ((!victim->dead && victim->aitype != passivetype &&
600 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
601 victim->id < Person::players.size())) {
602 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
603 return PersonType::types[creature].animFightIdle;
605 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
606 if (weapons[weaponids[weaponactive]].getType() == knife) {
607 return knifefightidleanim;
609 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1) {
610 return swordfightidlebothanim;
612 if (weapons[weaponids[weaponactive]].getType() == sword) {
613 return swordfightidleanim;
615 if (weapons[weaponids[weaponactive]].getType() == staff) {
616 return swordfightidleanim;
619 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause) {
620 return fightsidestep;
624 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype) {
627 if (howactive == typesitting) {
630 if (howactive == typesittingwall) {
633 if (howactive == typesleeping) {
636 if (howactive == typedead1) {
639 if (howactive == typedead2) {
642 if (howactive == typedead3) {
645 if (howactive == typedead4) {
648 return PersonType::types[creature].animBounceIdle;
652 * crouch animation for this creature
654 int Person::getCrouch()
656 return PersonType::types[creature].animCrouch;
660 * running animation for this creature (can be upright or all fours)
664 if (superruntoggle && (weaponactive == -1)) {
665 return PersonType::types[creature].animRunning;
667 return PersonType::types[creature].animRun;
673 int Person::getStop()
675 return PersonType::types[creature].animStop;
680 int Person::getLanding()
682 return PersonType::types[creature].animLanding;
687 int Person::getLandhard()
689 return PersonType::types[creature].animLandingHard;
695 * Person::DoAnimations
698 SolidHitBonus(int playerid)
700 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo) {
701 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
703 award_bonus(playerid, solidhit);
708 * spawns blood effects
710 void Person::DoBlood(float howmuch, int which)
712 // FIXME: should abstract out inputs
713 static int bleedxint, bleedyint;
715 if (bloodtoggle && !Tutorial::active) {
716 if (bleeding <= 0 && spurt) {
718 for (int i = 0; i < 3; i++) {
719 // emit blood particles
722 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
723 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
724 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
725 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
728 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
729 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
730 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
731 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
734 if (Random() % 2 == 0) { // 50% chance
735 for (int i = 0; i < 3; i++) {
736 if (Random() % 2 != 0) {
737 // emit teeth particles
740 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
741 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
744 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
745 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
749 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
751 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
753 Sprite::setLastSpriteSpecial(3); // sets it to teeth
759 // FIXME: manipulating attributes
760 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
763 while (PersonType::types[creature].bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || PersonType::types[creature].bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
764 bleedxint = abs(Random() % 512);
765 bleedyint = abs(Random() % 512);
769 bleedy /= realtexdetail;
770 bleedx /= realtexdetail;
771 direction = abs(Random() % 2) * 2 - 1;
780 * spawns big blood effects and ???
781 * modifies character's skin texture
783 void Person::DoBloodBig(float howmuch, int which)
785 static int bleedxint, bleedyint, i, j;
787 if (howmuch && id == 0) {
791 if (!Tutorial::active || id == 0) {
792 if (aitype != playercontrolled && howmuch > 0) {
796 if (creature == wolftype) {
797 int i = abs(Random() % 2);
799 whichsound = snarlsound;
802 whichsound = snarl2sound;
805 if (creature == rabbittype) {
806 int i = abs(Random() % 2);
808 whichsound = rabbitpainsound;
810 if (i == 1 && howmuch >= 2) {
811 whichsound = rabbitpain1sound;
815 if (whichsound != -1) {
816 emit_sound_at(whichsound, coords);
822 if (id == 0 && howmuch > 0) {
826 if (bloodtoggle && decalstoggle && !Tutorial::active) {
827 if (bleeding <= 0 && spurt) {
829 for (int i = 0; i < 3; i++) {
830 // emit blood particles
831 // FIXME: copypaste from above
834 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
835 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
836 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
837 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
840 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
841 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
842 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
843 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
848 // weird texture manipulation code follows.
849 // looks like this is painting blood onto the character's skin texture
850 // FIXME: surely there's a better way
852 int offsetx = 0, offsety = 0;
854 offsety = Random() % 40;
855 offsetx = abs(Random() % 60);
857 if (which == 190 || which == 185) {
858 offsety = Random() % 40;
859 offsetx = abs(Random() % 100) - 20;
862 offsety = Random() % 10;
863 offsetx = Random() % 10;
866 offsety = Random() % 20;
867 offsetx = Random() % 20;
869 if (which == 220 || which == 215) {
878 for (i = 0; i < 512; i++) {
879 for (j = 0; j < 512; j++) {
880 if (PersonType::types[creature].bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && PersonType::types[creature].bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
908 if (endx > 512 - 1) {
911 if (endy > 512 - 1) {
921 startx /= realtexdetail;
922 starty /= realtexdetail;
923 endx /= realtexdetail;
924 endy /= realtexdetail;
926 int texdetailint = realtexdetail;
928 for (i = startx; i < endx; i++) {
929 for (j = starty; j < endy; j++) {
930 if (PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
931 color = Random() % 85 + 170;
932 where = i * skeleton.skinsize * 3 + j * 3;
933 if (skeleton.skinText[where + 0] > color / 2) {
934 skeleton.skinText[where + 0] = color / 2;
936 skeleton.skinText[where + 1] = 0;
937 skeleton.skinText[where + 2] = 0;
941 skeleton.drawmodel.textureptr.bind();
946 while (PersonType::types[creature].bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || PersonType::types[creature].bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
947 bleedxint = abs(Random() % 512);
948 bleedyint = abs(Random() % 512);
950 bleedy = bleedxint + offsetx;
951 bleedx = bleedyint + offsety;
952 bleedy /= realtexdetail;
953 bleedx /= realtexdetail;
960 if (bleedx > skeleton.skinsize - 1) {
961 bleedx = skeleton.skinsize - 1;
963 if (bleedy > skeleton.skinsize - 1) {
964 bleedy = skeleton.skinsize - 1;
966 direction = abs(Random() % 2) * 2 - 1;
968 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
969 deathbleeding += bleeding;
970 bloodloss += bleeding * 3;
972 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
973 if (abs(Random() % 2) == 0) {
974 aitype = gethelptype;
977 aitype = attacktypecutoff;
987 * similar to DoBloodBig
989 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
993 static XYZ startpoint, endpoint, colpoint, movepoint;
994 static float rotationpoint;
996 static XYZ p1, p2, p3, p0;
999 float coordsx, coordsy;
1002 if (bloodtoggle && decalstoggle && !Tutorial::active) {
1004 if (!skeleton.free) {
1005 where = DoRotation(where, 0, -yaw, 0);
1009 startpoint.y += 100;
1014 // ray testing for a tri in the character model
1015 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
1016 if (whichtri != -1) {
1017 // low level geometry math
1019 p1 = skeleton.drawmodel.getTriangleVertex(whichtri, 0);
1020 p2 = skeleton.drawmodel.getTriangleVertex(whichtri, 1);
1021 p3 = skeleton.drawmodel.getTriangleVertex(whichtri, 2);
1023 bary.x = distsq(&p0, &p1);
1024 bary.y = distsq(&p0, &p2);
1025 bary.z = distsq(&p0, &p3);
1027 total = bary.x + bary.y + bary.z;
1032 bary.x = 1 - bary.x;
1033 bary.y = 1 - bary.y;
1034 bary.z = 1 - bary.z;
1036 total = bary.x + bary.y + bary.z;
1041 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1042 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1043 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1044 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1045 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1046 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1047 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;
1048 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;
1050 if (bleeding <= 0 && spurt) {
1052 for (int i = 0; i < 3; i++) {
1053 // emit blood particles
1054 // FIXME: more copypaste code
1056 if (skeleton.free) {
1057 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1058 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1059 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1060 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1063 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1064 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1065 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1066 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1071 // texture manipulation follows
1073 int offsetx = 0, offsety = 0;
1074 offsetx = (1 + coordsy) * 512 - 291;
1075 offsety = coordsx * 512 - 437;
1082 for (i = 0; i < 512; i++) {
1083 for (j = 0; j < 512; j++) {
1084 if (PersonType::types[creature].bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && PersonType::types[creature].bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1111 if (endx > 512 - 1) {
1114 if (endy > 512 - 1) {
1117 if (endx < startx) {
1120 if (endy < starty) {
1124 startx /= realtexdetail;
1125 starty /= realtexdetail;
1126 endx /= realtexdetail;
1127 endy /= realtexdetail;
1129 int texdetailint = realtexdetail;
1131 for (i = startx; i < endx; i++) {
1132 for (j = starty; j < endy; j++) {
1133 if (PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
1134 color = Random() % 85 + 170;
1135 where = i * skeleton.skinsize * 3 + j * 3;
1136 if (skeleton.skinText[where + 0] > color / 2) {
1137 skeleton.skinText[where + 0] = color / 2;
1139 skeleton.skinText[where + 1] = 0;
1140 skeleton.skinText[where + 2] = 0;
1141 } else if (PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= 160 + 4 && PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= 160 - 4) {
1142 color = Random() % 85 + 170;
1143 where = i * skeleton.skinsize * 3 + j * 3;
1144 if (skeleton.skinText[where + 0] > color / 2) {
1145 skeleton.skinText[where + 0] = color / 2;
1147 skeleton.skinText[where + 1] = 0;
1148 skeleton.skinText[where + 2] = 0;
1152 skeleton.drawmodel.textureptr.bind();
1155 bleedy = (1 + coordsy) * 512;
1156 bleedx = coordsx * 512;
1157 bleedy /= realtexdetail;
1158 bleedx /= realtexdetail;
1165 if (bleedx > skeleton.skinsize - 1) {
1166 bleedx = skeleton.skinsize - 1;
1168 if (bleedy > skeleton.skinsize - 1) {
1169 bleedy = skeleton.skinsize - 1;
1171 direction = abs(Random() % 2) * 2 - 1;
1173 if (whichtri == -1) {
1177 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1178 deathbleeding += bleeding;
1179 bloodloss += bleeding * 3;
1181 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1182 if (abs(Random() % 2) == 0) {
1183 aitype = gethelptype;
1186 aitype = attacktypecutoff;
1197 * guessing this performs a reversal
1199 void Person::Reverse()
1201 if (!((victim->aitype == playercontrolled || hostiletime > 1 || staggerdelay <= 0) && victim->animTarget != jumpupanim && victim->animTarget != jumpdownanim && (!Tutorial::active || cananger) && hostile)) {
1205 if (normaldotproduct(victim->facing, victim->coords - coords) > 0 && (victim->id != 0 || difficulty >= 2) && (creature != wolftype || victim->creature == wolftype)) {
1209 if (animTarget == sweepanim) {
1210 animTarget = sweepreversedanim;
1211 animCurrent = sweepreversedanim;
1212 victim->animCurrent = sweepreversalanim;
1213 victim->animTarget = sweepreversalanim;
1215 if (animTarget == spinkickanim) {
1216 animTarget = spinkickreversedanim;
1217 animCurrent = spinkickreversedanim;
1218 victim->animCurrent = spinkickreversalanim;
1219 victim->animTarget = spinkickreversalanim;
1221 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1222 if (animTarget == rabbittacklinganim) {
1225 victim->frameCurrent = 6;
1226 victim->frameTarget = 7;
1228 animTarget = upunchreversedanim;
1229 animCurrent = upunchreversedanim;
1230 victim->animCurrent = upunchreversalanim;
1231 victim->animTarget = upunchreversalanim;
1233 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1234 if (victim->weaponactive != -1) {
1235 victim->throwtogglekeydown = 1;
1236 XYZ tempVelocity = victim->velocity * .2;
1237 if (tempVelocity.x == 0) {
1238 tempVelocity.x = .1;
1240 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1241 victim->num_weapons--;
1242 if (victim->num_weapons) {
1243 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1244 if (victim->weaponstuck == victim->num_weapons) {
1245 victim->weaponstuck = 0;
1249 victim->weaponactive = -1;
1250 for (unsigned j = 0; j < Person::players.size(); j++) {
1251 Person::players[j]->wentforweapon = 0;
1255 animTarget = staffhitreversedanim;
1256 animCurrent = staffhitreversedanim;
1257 victim->animCurrent = staffhitreversalanim;
1258 victim->animTarget = staffhitreversalanim;
1260 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1261 if (victim->weaponactive != -1) {
1262 victim->throwtogglekeydown = 1;
1263 XYZ tempVelocity = victim->velocity * .2;
1264 if (tempVelocity.x == 0) {
1265 tempVelocity.x = .1;
1267 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1268 victim->num_weapons--;
1269 if (victim->num_weapons) {
1270 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1271 if (victim->weaponstuck == victim->num_weapons) {
1272 victim->weaponstuck = 0;
1276 victim->weaponactive = -1;
1277 for (unsigned j = 0; j < Person::players.size(); j++) {
1278 Person::players[j]->wentforweapon = 0;
1281 animTarget = staffspinhitreversedanim;
1282 animCurrent = staffspinhitreversedanim;
1283 victim->animCurrent = staffspinhitreversalanim;
1284 victim->animTarget = staffspinhitreversalanim;
1286 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1287 if (victim->weaponactive != -1) {
1288 victim->throwtogglekeydown = 1;
1289 XYZ tempVelocity = victim->velocity * .2;
1290 if (tempVelocity.x == 0) {
1291 tempVelocity.x = .1;
1293 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1294 victim->num_weapons--;
1295 if (victim->num_weapons) {
1296 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1297 if (victim->weaponstuck == victim->num_weapons) {
1298 victim->weaponstuck = 0;
1302 victim->weaponactive = -1;
1303 for (unsigned j = 0; j < Person::players.size(); j++) {
1304 Person::players[j]->wentforweapon = 0;
1307 animTarget = swordslashreversedanim;
1308 animCurrent = swordslashreversedanim;
1309 victim->animCurrent = swordslashreversalanim;
1310 victim->animTarget = swordslashreversalanim;
1312 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1313 if (victim->weaponactive != -1) {
1314 victim->throwtogglekeydown = 1;
1315 XYZ tempVelocity = victim->velocity * .2;
1316 if (tempVelocity.x == 0) {
1317 tempVelocity.x = .1;
1319 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1320 victim->num_weapons--;
1321 if (victim->num_weapons) {
1322 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1323 if (victim->weaponstuck == victim->num_weapons) {
1324 victim->weaponstuck = 0;
1328 victim->weaponactive = -1;
1329 for (unsigned j = 0; j < Person::players.size(); j++) {
1330 Person::players[j]->wentforweapon = 0;
1333 animTarget = knifeslashreversedanim;
1334 animCurrent = knifeslashreversedanim;
1335 victim->animCurrent = knifeslashreversalanim;
1336 victim->animTarget = knifeslashreversalanim;
1338 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1339 victim->targettilt2 = targettilt2;
1340 victim->frameCurrent = frameCurrent;
1341 victim->frameTarget = frameTarget;
1342 victim->target = target;
1343 victim->velocity = 0;
1344 victim->oldcoords = victim->coords;
1345 victim->coords = coords;
1346 victim->targetyaw = targetyaw;
1347 victim->yaw = targetyaw;
1348 victim->victim = this->shared_from_this();
1350 if (animTarget == winduppunchanim) {
1351 animTarget = winduppunchblockedanim;
1352 victim->animTarget = blockhighleftanim;
1353 victim->frameTarget = 1;
1354 victim->target = .5;
1355 victim->victim = this->shared_from_this();
1356 victim->targetyaw = targetyaw + 180;
1358 if (animTarget == wolfslapanim) {
1359 animTarget = winduppunchblockedanim;
1360 victim->animTarget = blockhighleftanim;
1361 victim->frameTarget = 1;
1362 victim->target = .5;
1363 victim->victim = this->shared_from_this();
1364 victim->targetyaw = targetyaw + 180;
1366 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1367 animTarget = swordslashparriedanim;
1368 parriedrecently = .4;
1369 victim->parriedrecently = 0;
1370 victim->animTarget = swordslashparryanim;
1371 victim->frameTarget = 1;
1372 victim->target = .5;
1373 victim->victim = this->shared_from_this();
1374 victim->targetyaw = targetyaw + 180;
1376 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1377 if (victim->weaponactive != -1) {
1378 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1379 if (weapons[victim->weaponids[0]].getType() == staff) {
1380 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1382 if (weapons[weaponids[0]].getType() == staff) {
1383 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1385 emit_sound_at(swordstaffsound, victim->coords);
1387 emit_sound_at(metalhitsound, victim->coords);
1391 victim->Puff(righthand);
1393 victim->frameTarget = 0;
1394 victim->animTarget = staggerbackhighanim;
1395 victim->targetyaw = targetyaw + 180;
1397 aim = DoRotation(facing, 0, 90, 0) * 21;
1399 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1400 victim->num_weapons--;
1401 if (victim->num_weapons) {
1402 victim->weaponids[0] = victim->weaponids[num_weapons];
1403 if (victim->weaponstuck == victim->num_weapons) {
1404 victim->weaponstuck = 0;
1407 victim->weaponactive = -1;
1408 for (unsigned i = 0; i < Person::players.size(); i++) {
1409 Person::players[i]->wentforweapon = 0;
1413 if (abs(Random() % 20) == 0) {
1414 if (weaponactive != -1) {
1415 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1416 if (weapons[victim->weaponids[0]].getType() == staff) {
1417 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1419 if (weapons[weaponids[0]].getType() == staff) {
1420 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1423 emit_sound_at(swordstaffsound, coords);
1425 emit_sound_at(metalhitsound, coords);
1433 animTarget = staggerbackhighanim;
1434 targetyaw = targetyaw + 180;
1436 aim = DoRotation(facing, 0, 90, 0) * 21;
1438 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1441 weaponids[0] = weaponids[num_weapons];
1442 if (weaponstuck == num_weapons) {
1447 for (unsigned i = 0; i < Person::players.size(); i++) {
1448 Person::players[i]->wentforweapon = 0;
1453 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1454 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1455 victim->animTarget = dodgebackanim;
1456 victim->frameTarget = 0;
1460 rotatetarget = coords - victim->coords;
1461 Normalise(&rotatetarget);
1462 victim->targetyaw = -asin(0 - rotatetarget.x);
1463 victim->targetyaw *= 360 / 6.28;
1464 if (rotatetarget.z < 0) {
1465 victim->targetyaw = 180 - victim->targetyaw;
1468 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1470 victim->lastattack3 = victim->lastattack2;
1471 victim->lastattack2 = victim->lastattack;
1472 victim->lastattack = victim->animTarget;
1474 victim->animTarget = sweepanim;
1475 victim->frameTarget = 0;
1479 rotatetarget = coords - victim->coords;
1480 Normalise(&rotatetarget);
1481 victim->targetyaw = -asin(0 - rotatetarget.x);
1482 victim->targetyaw *= 360 / 6.28;
1483 if (rotatetarget.z < 0) {
1484 victim->targetyaw = 180 - victim->targetyaw;
1487 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1489 victim->lastattack3 = victim->lastattack2;
1490 victim->lastattack2 = victim->lastattack;
1491 victim->lastattack = victim->animTarget;
1497 victim->velocity = 0;
1499 if (aitype != playercontrolled) {
1501 if (escapednum < 2) {
1502 int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
1503 if ((Random() % chances) == 0) {
1509 if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal) {
1517 void Person::DoDamage(float howmuch)
1521 damagetaken += howmuch / power;
1523 damagedealt += howmuch / power;
1527 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo)) {
1532 if (!Tutorial::active) {
1533 damage += howmuch / power;
1534 permanentdamage += howmuch / 2 / power;
1535 superpermanentdamage += howmuch / 4 / power;
1538 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2) {
1541 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt) {
1546 camerashake += howmuch / 100;
1547 if ((howmuch > 50 && damage > damagetolerance / 2)) {
1548 blackout = damage / damagetolerance;
1556 if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile)) {
1557 aitype = attacktypecutoff;
1559 if (!Tutorial::active && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1560 if (abs(Random() % 2) == 0) {
1561 aitype = gethelptype;
1564 aitype = attacktypecutoff;
1569 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1572 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1573 if (skeleton.free) {
1574 flatvelocity2 = skeleton.joints[i].velocity;
1575 flatfacing2 = skeleton.joints[i].position * scale + coords;
1577 flatvelocity2 = velocity;
1578 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1580 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1581 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1582 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1583 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1584 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1585 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1588 emit_sound_at(splattersound, coords);
1593 if (!dead && creature == wolftype) {
1594 award_bonus(0, Wolfbonus);
1601 if (!Tutorial::active || id == 0) {
1602 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1603 int whichsound = -1;
1605 if (creature == wolftype) {
1606 int i = abs(Random() % 2);
1608 whichsound = snarlsound;
1611 whichsound = snarl2sound;
1614 if (creature == rabbittype) {
1615 int i = abs(Random() % 2);
1617 whichsound = rabbitpainsound;
1619 if (i == 1 && damage > damagetolerance) {
1620 whichsound = rabbitpain1sound;
1624 if (whichsound != -1) {
1625 emit_sound_at(whichsound, coords);
1626 addEnvSound(coords);
1634 * calculate/animate head facing direction?
1636 void Person::DoHead()
1638 static XYZ rotatearound;
1640 static float lookspeed = 500;
1642 if (!freeze && !winfreeze) {
1645 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1646 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1648 while (targetheadyaw > 180) {
1649 targetheadyaw -= 360;
1651 while (targetheadyaw < -180) {
1652 targetheadyaw += 360;
1655 if (targetheadyaw > 160) {
1656 targetheadpitch = targetheadpitch * -1;
1658 if (targetheadyaw < -160) {
1659 targetheadpitch = targetheadpitch * -1;
1661 if (targetheadyaw > 160) {
1662 targetheadyaw = targetheadyaw - 180;
1664 if (targetheadyaw < -160) {
1665 targetheadyaw = targetheadyaw + 180;
1668 if (targetheadpitch > 120) {
1669 targetheadpitch = 120;
1671 if (targetheadpitch < -120) {
1672 targetheadpitch = -120;
1674 if (targetheadyaw > 120) {
1675 targetheadyaw = 120;
1677 if (targetheadyaw < -120) {
1678 targetheadyaw = -120;
1682 targetheadpitch = 0;
1685 if (targetheadyaw > 80) {
1688 if (targetheadyaw < -80) {
1689 targetheadyaw = -80;
1691 if (targetheadpitch > 50) {
1692 targetheadpitch = 50;
1694 if (targetheadpitch < -50) {
1695 targetheadpitch = -50;
1699 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed) {
1700 headyaw = targetheadyaw;
1701 } else if (headyaw > targetheadyaw) {
1702 headyaw -= multiplier * lookspeed;
1703 } else if (headyaw < targetheadyaw) {
1704 headyaw += multiplier * lookspeed;
1707 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2) {
1708 headpitch = targetheadpitch;
1709 } else if (headpitch > targetheadpitch) {
1710 headpitch -= multiplier * lookspeed / 2;
1711 } else if (headpitch < targetheadpitch) {
1712 headpitch += multiplier * lookspeed / 2;
1715 rotatearound = jointPos(neck);
1716 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1720 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1721 facing = DoRotation(facing, headpitch * .4, 0, 0);
1722 facing = DoRotation(facing, 0, headyaw * .4, 0);
1725 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1726 facing = DoRotation(facing, headpitch * .8, 0, 0);
1727 facing = DoRotation(facing, 0, headyaw * .8, 0);
1730 if (animTarget == walkanim) {
1731 facing = DoRotation(facing, headpitch * .6, 0, 0);
1732 facing = DoRotation(facing, 0, headyaw * .6, 0);
1735 skeleton.specialforward[0] = facing;
1736 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1737 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
1738 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1739 skeleton.FindRotationMuscle(i, animTarget);
1746 * ragdolls character?
1748 void Person::RagDoll(bool checkcollision)
1753 if (!skeleton.free) {
1757 if (id == 0 && isFlip()) {
1765 facing = DoRotation(facing, 0, yaw, 0);
1767 skeleton.freetime = 0;
1769 skeleton.longdead = 0;
1772 skeleton.broken = 0;
1773 skeleton.spinny = 1;
1775 skeleton.freefall = 1;
1777 if (!isnormal(velocity.x)) {
1780 if (!isnormal(velocity.y)) {
1783 if (!isnormal(velocity.z)) {
1786 if (!isnormal(yaw)) {
1789 if (!isnormal(coords.x)) {
1792 if (!isnormal(tilt)) {
1795 if (!isnormal(tilt2)) {
1799 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1800 skeleton.joints[i].delay = 0;
1801 skeleton.joints[i].locked = 0;
1802 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1803 if (!isnormal(skeleton.joints[i].position.x)) {
1804 skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1806 if (!isnormal(skeleton.joints[i].position.x)) {
1807 skeleton.joints[i].position = coords;
1809 skeleton.joints[i].position.y += .1;
1810 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1811 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1814 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1815 skeleton.joints[i].velocity = 0;
1816 skeleton.joints[i].velchange = 0;
1818 skeleton.DoConstraints(&coords, &scale);
1819 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
1820 skeleton.DoConstraints(&coords, &scale);
1821 skeleton.DoConstraints(&coords, &scale);
1822 skeleton.DoConstraints(&coords, &scale);
1823 skeleton.DoConstraints(&coords, &scale);
1826 speed = targetFrame().speed * 2;
1827 if (currentFrame().speed > targetFrame().speed) {
1828 speed = currentFrame().speed * 2;
1831 speed = transspeed * 2;
1836 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1837 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height) {
1838 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);
1840 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1842 change.x = (float)(Random() % 100) / 100;
1843 change.y = (float)(Random() % 100) / 100;
1844 change.z = (float)(Random() % 100) / 100;
1845 skeleton.joints[i].velocity += change;
1846 skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change;
1848 change.x = (float)(Random() % 100) / 100;
1849 change.y = (float)(Random() % 100) / 100;
1850 change.z = (float)(Random() % 100) / 100;
1851 skeleton.joints[i].velchange += change;
1852 skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change;
1855 if (checkcollision) {
1858 if (!skeleton.joints.empty()) {
1861 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1862 average += skeleton.joints[j].position;
1864 average /= skeleton.joints.size();
1865 coords += average * scale;
1866 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1867 skeleton.joints[j].position -= average;
1871 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1872 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1873 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
1874 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1877 if (SphereCheck(&lowpoint, 3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
1878 coords.x = lowpoint.x;
1879 coords.z = lowpoint.z;
1888 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1889 velocity += skeleton.joints[i].velocity * scale;
1891 velocity /= skeleton.joints.size();
1894 if (Random() % 2 == 0) {
1895 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1896 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1897 weapons[weaponids[0]].velocity.x += .01;
1900 weaponids[0] = weaponids[num_weapons];
1901 if (weaponstuck == num_weapons) {
1906 for (unsigned i = 0; i < Person::players.size(); i++) {
1907 Person::players[i]->wentforweapon = 0;
1912 animTarget = bounceidleanim;
1913 animCurrent = bounceidleanim;
1921 void Person::FootLand(bodypart whichfoot, float opacity)
1923 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
1924 cerr << "FootLand called on wrong bodypart" << endl;
1927 static XYZ terrainlight;
1928 static XYZ footvel, footpoint;
1929 if (opacity >= 1 || skiddelay <= 0) {
1932 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1933 if (distsq(&footpoint, &viewer)) {
1934 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1936 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1937 footvel = velocity / 5;
1938 if (footvel.y < .8) {
1941 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1942 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1943 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1944 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1945 if (environment == snowyenvironment) {
1946 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1948 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1950 } else if (environment == grassyenvironment) {
1951 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1952 } else if (environment == desertenvironment) {
1953 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1955 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1959 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
1960 footvel = velocity / 5;
1961 if (footvel.y < .8) {
1964 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1965 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1966 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1973 * make a puff effect at a body part (dust effect?)
1975 void Person::Puff(int whichlabel)
1977 static XYZ footvel, footpoint;
1980 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1981 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1985 * I think I added this in an attempt to clean up code
1987 void Person::setTargetAnimation(int animation)
1989 animTarget = animation;
1998 void Person::DoAnimations()
2000 if (!skeleton.free) {
2001 static float oldtarget;
2003 if (isIdle() && animCurrent != getIdle()) {
2004 normalsupdatedelay = 0;
2007 if (animTarget == tempanim || animCurrent == tempanim) {
2008 Animation::animations[tempanim] = tempanimation;
2010 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
2017 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
2018 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
2020 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z)) {
2023 if (!crouchkeydown && velocity.y >= -15) {
2027 if ((animCurrent == jumpupanim || animTarget == jumpdownanim) /*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
2032 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
2034 if (normaldotproduct(targfacing, velocity) >= -.3) {
2035 animTarget = flipanim;
2037 animTarget = backflipanim;
2039 crouchtogglekeydown = 1;
2048 if (Animation::animations[animTarget].attack != reversed) {
2051 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
2052 crouchtogglekeydown = 0;
2053 if (aitype == playercontrolled) {
2057 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain)) {
2061 crouchtogglekeydown = 1;
2065 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
2067 normalsupdatedelay = 0;
2072 if (animTarget == rollanim && frameTarget == 3 && onfire) {
2074 emit_sound_at(fireendsound, coords);
2075 pause_sound(stream_firesound);
2079 if (animTarget == rabbittacklinganim && frameTarget == 1) {
2080 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0) {
2083 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
2084 if (normaldotproduct(victim->facing, facing) > 0) {
2085 victim->animTarget = rabbittackledbackanim;
2087 victim->animTarget = rabbittackledfrontanim;
2089 victim->frameTarget = 2;
2092 victim->targetyaw = yaw;
2093 if (victim->aitype == gethelptype) {
2094 victim->DoDamage(victim->damagetolerance - victim->damage);
2096 //victim->DoDamage(30);
2097 if (creature == wolftype) {
2099 emit_sound_at(clawslicesound, victim->coords);
2101 victim->DoBloodBig(1 / victim->armorhead, 210);
2103 award_bonus(id, TackleBonus,
2104 victim->aitype == gethelptype ? 50 : 0);
2108 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2109 if (weapons[weaponids[0]].getType() == knife) {
2110 if (weaponactive == -1) {
2112 } else if (weaponactive == 0) {
2116 if (weaponactive == -1) {
2117 emit_sound_at(knifesheathesound, coords);
2119 if (weaponactive != -1) {
2120 emit_sound_at(knifedrawsound, coords, 128);
2123 drawtogglekeydown = 1;
2126 if (!Tutorial::active || id == 0) {
2127 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2128 int whichsound = -1;
2130 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2131 if (targetFrame().label == 1) {
2132 whichsound = footstepsound;
2134 whichsound = footstepsound2;
2136 if (targetFrame().label == 1) {
2137 FootLand(leftfoot, 1);
2139 if (targetFrame().label == 2) {
2140 FootLand(rightfoot, 1);
2142 if (targetFrame().label == 3 && isRun()) {
2143 FootLand(rightfoot, 1);
2144 FootLand(leftfoot, 1);
2147 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2148 if (targetFrame().label == 1) {
2149 whichsound = footstepsound3;
2151 whichsound = footstepsound4;
2156 if (targetFrame().label == 1) {
2157 whichsound = footstepsound3;
2159 whichsound = footstepsound4;
2162 if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2163 if (Animation::animations[animTarget].attack != neutral) {
2164 unsigned r = abs(Random() % 3);
2166 whichsound = lowwhooshsound;
2169 whichsound = midwhooshsound;
2172 whichsound = highwhooshsound;
2175 if (Animation::animations[animTarget].attack == neutral) {
2176 whichsound = movewhooshsound;
2178 } else if (targetFrame().label == 4) {
2179 whichsound = knifeswishsound;
2181 if (targetFrame().label == 8 && !Tutorial::active) {
2182 whichsound = landsound2;
2185 if (whichsound != -1) {
2186 emit_sound_at(whichsound, coords, 256.);
2189 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2190 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2191 addEnvSound(coords, 15);
2193 addEnvSound(coords, 6);
2198 if (targetFrame().label == 3) {
2200 emit_sound_at(whichsound, coords, 128.);
2207 if (!Tutorial::active || id == 0) {
2208 if (speechdelay <= 0) {
2209 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
2210 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2211 int whichsound = -1;
2212 if (targetFrame().label == 4 && aitype != playercontrolled) {
2213 if (Animation::animations[animTarget].attack != neutral) {
2214 unsigned r = abs(Random() % 4);
2215 whichsound = PersonType::types[creature].soundsAttack[r];
2220 if (whichsound != -1) {
2221 emit_sound_at(whichsound, coords);
2228 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2229 FootLand(leftfoot, 1);
2230 FootLand(rightfoot, 1);
2234 currentoffset = targetoffset;
2235 frameTarget = frameCurrent;
2236 animCurrent = animTarget;
2239 if (animCurrent == removeknifeanim && currentFrame().label == 5) {
2240 for (unsigned i = 0; i < weapons.size(); i++) {
2241 if (weapons[i].owner == -1) {
2242 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2243 if (distsq(&coords, &weapons[i].position) >= 1) {
2244 if (weapons[i].getType() != staff) {
2245 emit_sound_at(knifedrawsound, coords, 128.);
2255 if (animCurrent == crouchremoveknifeanim && currentFrame().label == 5) {
2256 for (unsigned i = 0; i < weapons.size(); i++) {
2257 bool willwork = true;
2258 if (weapons[i].owner != -1) {
2259 if (Person::players[weapons[i].owner]->weaponstuck != -1) {
2260 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i)) {
2261 if (Person::players[weapons[i].owner]->num_weapons > 1) {
2267 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free)) {
2268 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2269 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2270 bool fleshstuck = false;
2271 if (weapons[i].owner != -1) {
2272 if (victim->weaponstuck != -1) {
2273 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2279 emit_sound_at(fleshstabremovesound, coords, 128.);
2281 if (weapons[i].getType() != staff) {
2282 emit_sound_at(knifedrawsound, coords, 128.);
2285 if (weapons[i].owner != -1) {
2286 victim = Person::players[weapons[i].owner];
2287 if (victim->num_weapons == 1) {
2288 victim->num_weapons = 0;
2290 victim->num_weapons = 1;
2293 //victim->weaponactive=-1;
2294 victim->skeleton.longdead = 0;
2295 victim->skeleton.free = 1;
2296 victim->skeleton.broken = 0;
2298 for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) {
2299 victim->skeleton.joints[j].velchange = 0;
2300 victim->skeleton.joints[j].locked = 0;
2306 Normalise(&relative);
2307 XYZ footvel, footpoint;
2309 footpoint = weapons[i].position;
2310 if (victim->weaponstuck != -1) {
2311 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2313 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2315 weapons[i].bloody = 2;
2316 weapons[i].blooddrip = 5;
2317 victim->weaponstuck = -1;
2320 if (victim->num_weapons > 0) {
2321 if (victim->weaponstuck != 0 && victim->weaponstuck != -1) {
2322 victim->weaponstuck = 0;
2324 if (victim->weaponids[0] == int(i)) {
2325 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2329 victim->jointVel(abdomen) += relative * 6;
2330 victim->jointVel(neck) += relative * 6;
2331 victim->jointVel(rightshoulder) += relative * 6;
2332 victim->jointVel(leftshoulder) += relative * 6;
2341 if (animCurrent == drawleftanim && currentFrame().label == 5) {
2342 if (weaponactive == -1) {
2344 } else if (weaponactive == 0) {
2346 if (num_weapons == 2) {
2348 buffer = weaponids[0];
2349 weaponids[0] = weaponids[1];
2350 weaponids[1] = buffer;
2353 if (weaponactive == -1) {
2354 emit_sound_at(knifesheathesound, coords, 128.);
2356 if (weaponactive != -1) {
2357 emit_sound_at(knifedrawsound, coords, 128.);
2361 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2362 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2363 Normalise(&rotatetarget);
2364 targetyaw = -asin(0 - rotatetarget.x);
2365 targetyaw *= 360 / 6.28;
2366 if (rotatetarget.z < 0) {
2367 targetyaw = 180 - targetyaw;
2370 if (animTarget == walljumprightkickanim) {
2373 if (animTarget == walljumpleftkickanim) {
2380 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0)) {
2384 if (distsq(&victim->coords, &/*Person::players[i]->*/ coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1) {
2392 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2393 animTarget = rabbittackleanim;
2395 emit_sound_at(jumpsound, coords);
2403 targetloc = velocity;
2404 Normalise(&targetloc);
2405 targetloc += coords;
2406 for (unsigned i = 0; i < Person::players.size(); i++) {
2408 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2409 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2414 if (closestid != -1) {
2415 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2417 victim = Person::players[closestid];
2418 coords = victim->coords;
2419 animCurrent = rabbittacklinganim;
2420 animTarget = rabbittacklinganim;
2424 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2425 rotatetarget = coords - victim->coords;
2426 Normalise(&rotatetarget);
2427 targetyaw = -asin(0 - rotatetarget.x);
2428 targetyaw *= 360 / 6.28;
2429 if (rotatetarget.z < 0) {
2430 targetyaw = 180 - targetyaw;
2433 if (animTarget != rabbitrunninganim) {
2434 emit_sound_at(jumpsound, coords, 128.);
2441 float damagemult = PersonType::types[creature].power * power;
2443 damagemult /= victim->damagetolerance / 200;
2445 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)) {
2446 if (animCurrent == spinkickanim && currentFrame().label == 5) {
2447 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2452 if (Random() % 2 || creature == wolftype) {
2455 if (creature == wolftype) {
2459 if (!Tutorial::active) {
2460 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2462 if (creature == wolftype) {
2463 emit_sound_at(clawslicesound, victim->coords, 128.);
2465 victim->DoBloodBig(2 / victim->armorhead, 175);
2469 relative = victim->coords - coords;
2471 Normalise(&relative);
2472 relative = DoRotation(relative, 0, -90, 0);
2473 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2474 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2476 victim->jointVel(head) += relative * damagemult * 200;
2478 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2484 if (animCurrent == wolfslapanim && currentFrame().label == 5) {
2485 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2490 if (Random() % 2 || creature == wolftype) {
2492 if (creature == wolftype) {
2496 emit_sound_at(whooshhitsound, victim->coords);
2497 if (creature == wolftype) {
2498 emit_sound_at(clawslicesound, victim->coords, 128.);
2500 victim->DoBloodBig(2, 175);
2504 relative = victim->coords - coords;
2506 Normalise(&relative);
2508 Normalise(&relative);
2509 relative = DoRotation(relative, 0, 90, 0);
2510 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2511 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2513 victim->jointVel(head) += relative * damagemult * 100;
2515 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2519 if (animCurrent == walljumprightkickanim && currentFrame().label == 5) {
2520 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2527 if (!Tutorial::active) {
2528 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2530 if (creature == wolftype) {
2531 emit_sound_at(clawslicesound, victim->coords, 128.);
2533 victim->DoBloodBig(2 / victim->armorhead, 175);
2539 Normalise(&relative);
2540 relative = DoRotation(relative, 0, -90, 0);
2541 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2542 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2544 victim->jointVel(head) += relative * damagemult * 200;
2546 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2548 if (victim->damage > victim->damagetolerance) {
2549 award_bonus(id, style);
2556 if (animCurrent == walljumpleftkickanim && currentFrame().label == 5) {
2557 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2564 if (!Tutorial::active) {
2565 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2567 if (creature == wolftype) {
2568 emit_sound_at(clawslicesound, victim->coords, 128.);
2570 victim->DoBloodBig(2 / victim->armorhead, 175);
2576 Normalise(&relative);
2577 relative = DoRotation(relative, 0, 90, 0);
2578 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2579 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2581 victim->jointVel(head) += relative * damagemult * 200;
2583 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2585 if (victim->damage > victim->damagetolerance) {
2586 award_bonus(id, style);
2593 if (animCurrent == blockhighleftstrikeanim && currentFrame().label == 5) {
2594 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2603 emit_sound_at(whooshhitsound, victim->coords);
2606 relative = victim->coords - coords;
2608 Normalise(&relative);
2609 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2610 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2612 victim->jointVel(head) += relative * damagemult * 100;
2614 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2618 if (animCurrent == killanim && currentFrame().label == 8) {
2619 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2624 emit_sound_at(whooshhitsound, victim->coords, 128.);
2626 victim->skeleton.longdead = 0;
2627 victim->skeleton.free = 1;
2628 victim->skeleton.broken = 0;
2629 victim->skeleton.spinny = 1;
2631 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2632 victim->skeleton.joints[i].velchange = 0;
2633 victim->skeleton.joints[i].delay = 0;
2634 victim->skeleton.joints[i].locked = 0;
2635 //victim->skeleton.joints[i].velocity=0;
2641 Normalise(&relative);
2642 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2643 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2644 victim->skeleton.joints[i].position.y += relative.y * .3;
2645 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2646 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2648 victim->Puff(abdomen);
2649 victim->jointVel(abdomen).y = relative.y * 400;
2653 if (animCurrent == killanim && currentFrame().label == 5) {
2654 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2659 if (!Tutorial::active) {
2660 emit_sound_at(heavyimpactsound, coords, 128.);
2663 relative = victim->coords - coords;
2665 Normalise(&relative);
2666 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2667 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2669 victim->Puff(abdomen);
2670 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2674 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2675 victim->jointVel(abdomen) += relative * damagemult * 300;
2679 if (animCurrent == dropkickanim && currentFrame().label == 7) {
2680 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2685 if (!Tutorial::active) {
2686 emit_sound_at(thudsound, coords);
2689 victim->skeleton.longdead = 0;
2690 victim->skeleton.free = 1;
2691 victim->skeleton.broken = 0;
2692 victim->skeleton.spinny = 1;
2694 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2695 victim->skeleton.joints[i].velchange = 0;
2696 //victim->skeleton.joints[i].delay=0;
2697 victim->skeleton.joints[i].locked = 0;
2700 relative = victim->coords - coords;
2701 Normalise(&relative);
2703 Normalise(&relative);
2704 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2705 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2707 if (!victim->dead) {
2711 victim->Puff(abdomen);
2712 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2713 victim->jointVel(abdomen) += relative * damagemult * 200;
2715 if (!victim->dead) {
2721 if ((animCurrent == crouchstabanim || animCurrent == swordgroundstabanim) && currentFrame().label == 5) {
2724 if (!victim->skeleton.free) {
2730 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2731 emit_sound_at(knifesheathesound, coords, 128.);
2734 if (victim && hasvictim) {
2735 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2737 XYZ where, startpoint, endpoint, movepoint, colpoint;
2738 float rotationpoint;
2740 if (weapons[weaponids[weaponactive]].getType() == knife) {
2741 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2742 where -= victim->coords;
2743 if (!victim->skeleton.free) {
2744 where = DoRotation(where, 0, -victim->yaw, 0);
2748 startpoint.y += 100;
2752 if (weapons[weaponids[weaponactive]].getType() == sword) {
2753 where = weapons[weaponids[weaponactive]].position;
2754 where -= victim->coords;
2755 if (!victim->skeleton.free) {
2756 where = DoRotation(where, 0, -victim->yaw, 0);
2759 where = weapons[weaponids[weaponactive]].tippoint;
2760 where -= victim->coords;
2761 if (!victim->skeleton.free) {
2762 where = DoRotation(where, 0, -victim->yaw, 0);
2766 if (weapons[weaponids[weaponactive]].getType() == staff) {
2767 where = weapons[weaponids[weaponactive]].position;
2768 where -= victim->coords;
2769 if (!victim->skeleton.free) {
2770 where = DoRotation(where, 0, -victim->yaw, 0);
2773 where = weapons[weaponids[weaponactive]].tippoint;
2774 where -= victim->coords;
2775 if (!victim->skeleton.free) {
2776 where = DoRotation(where, 0, -victim->yaw, 0);
2782 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2784 if (whichtri != -1) {
2785 if (victim->dead != 2) {
2786 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2787 if (!victim->dead) {
2788 award_bonus(id, FinishedBonus);
2792 weapons[weaponids[weaponactive]].bloody = 2;
2795 victim->skeleton.longdead = 0;
2796 victim->skeleton.free = 1;
2797 victim->skeleton.broken = 0;
2799 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2800 victim->skeleton.joints[i].velchange = 0;
2801 victim->skeleton.joints[i].locked = 0;
2802 //victim->skeleton.joints[i].velocity=0;
2804 emit_sound_at(fleshstabsound, coords, 128);
2806 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2807 weapons[weaponids[weaponactive]].blooddrip += 5;
2808 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2810 if (whichtri == -1) {
2812 emit_sound_at(knifesheathesound, coords, 128.);
2818 if ((animCurrent == crouchstabanim || animCurrent == swordgroundstabanim) && currentFrame().label == 6) {
2820 emit_sound_at(knifedrawsound, coords, 128);
2823 if (victim && hasvictim) {
2824 XYZ footvel, footpoint;
2826 emit_sound_at(fleshstabremovesound, coords, 128.);
2829 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2831 if (weapons[weaponids[weaponactive]].getType() == sword) {
2832 XYZ where, startpoint, endpoint, movepoint;
2833 float rotationpoint;
2836 where = weapons[weaponids[weaponactive]].position;
2837 where -= victim->coords;
2838 if (!victim->skeleton.free) {
2839 where = DoRotation(where, 0, -victim->yaw, 0);
2842 where = weapons[weaponids[weaponactive]].tippoint;
2843 where -= victim->coords;
2844 if (!victim->skeleton.free) {
2845 where = DoRotation(where, 0, -victim->yaw, 0);
2851 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2852 footpoint += victim->coords;
2854 if (whichtri == -1) {
2855 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2858 if (weapons[weaponids[weaponactive]].getType() == staff) {
2859 XYZ where, startpoint, endpoint, movepoint;
2860 float rotationpoint;
2863 where = weapons[weaponids[weaponactive]].position;
2864 where -= victim->coords;
2865 if (!victim->skeleton.free) {
2866 where = DoRotation(where, 0, -victim->yaw, 0);
2869 where = weapons[weaponids[weaponactive]].tippoint;
2870 where -= victim->coords;
2871 if (!victim->skeleton.free) {
2872 where = DoRotation(where, 0, -victim->yaw, 0);
2878 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2879 footpoint += victim->coords;
2881 if (whichtri == -1) {
2882 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2885 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2887 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2888 victim->skeleton.longdead = 0;
2889 victim->skeleton.free = 1;
2890 victim->skeleton.broken = 0;
2892 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2893 victim->skeleton.joints[i].velchange = 0;
2894 victim->skeleton.joints[i].locked = 0;
2895 //victim->skeleton.joints[i].velocity=0;
2901 Normalise(&relative);
2902 //victim->Puff(abdomen);
2904 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2907 if (victim->bloodloss < victim->damagetolerance) {
2908 victim->bloodloss += 1000;
2912 victim->jointVel(abdomen) += relative * damagemult * 20;
2916 if (!hasvictim && onterrain) {
2917 weapons[weaponids[weaponactive]].bloody = 0;
2918 weapons[weaponids[weaponactive]].blooddrip = 0;
2922 if (animCurrent == upunchanim && currentFrame().label == 5) {
2923 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2932 if (!Tutorial::active) {
2933 emit_sound_at(heavyimpactsound, victim->coords, 128);
2938 relative = victim->coords - coords;
2940 Normalise(&relative);
2941 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2942 victim->skeleton.joints[i].velocity = relative * 30;
2944 victim->jointVel(head) += relative * damagemult * 150;
2946 victim->frameTarget = 0;
2947 victim->animTarget = staggerbackhardanim;
2948 victim->targetyaw = targetyaw + 180;
2950 victim->stunned = 1;
2953 victim->Puff(abdomen);
2954 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2960 if (animCurrent == winduppunchanim && currentFrame().label == 5) {
2961 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2966 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
2967 if (!Tutorial::active) {
2968 emit_sound_at(thudsound, victim->coords);
2970 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
2971 if (!Tutorial::active) {
2972 emit_sound_at(whooshhitsound, victim->coords);
2975 if (!Tutorial::active) {
2976 emit_sound_at(heavyimpactsound, victim->coords);
2980 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight) {
2984 relative = victim->coords - coords;
2986 Normalise(&relative);
2988 Normalise(&relative);
2989 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2990 victim->skeleton.joints[i].velocity = relative * 5;
2992 victim->jointVel(abdomen) += relative * damagemult * 400;
2994 victim->frameTarget = 0;
2995 victim->animTarget = staggerbackhardanim;
2996 victim->targetyaw = targetyaw + 180;
2998 victim->stunned = 1;
3000 victim->Puff(abdomen);
3001 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
3007 if (animCurrent == blockhighleftanim && currentFrame().label == 5) {
3008 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3009 if (victim->id == 0) {
3012 emit_sound_at(landsound2, victim->coords);
3018 if (animCurrent == swordslashparryanim && currentFrame().label == 5) {
3019 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3020 if (victim->id == 0) {
3024 if (weaponactive != -1) {
3025 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3026 if (weapons[victim->weaponids[0]].getType() == staff) {
3027 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3029 if (weapons[weaponids[0]].getType() == staff) {
3030 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3033 emit_sound_at(swordstaffsound, victim->coords);
3035 emit_sound_at(metalhitsound, victim->coords);
3043 if (animCurrent == knifethrowanim && currentFrame().label == 5) {
3044 if (weaponactive != -1) {
3047 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);
3049 weapons[weaponids[0]].thrown(aim * 50);
3052 weaponids[0] = weaponids[num_weapons];
3058 if (animCurrent == knifeslashstartanim && currentFrame().label == 5) {
3060 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 && victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
3062 if (!Tutorial::active) {
3063 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
3066 award_bonus(id, Slicebonus);
3067 if (!Tutorial::active) {
3068 emit_sound_at(knifeslicesound, victim->coords);
3070 //victim->jointVel(abdomen)+=relative*damagemult*200;
3071 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
3072 if (victim->id != 0 || difficulty == 2) {
3073 victim->frameTarget = 0;
3074 victim->animTarget = staggerbackhardanim;
3075 victim->targetyaw = targetyaw + 180;
3079 victim->lowreversaldelay = 0;
3080 victim->highreversaldelay = 0;
3081 if (aitype != playercontrolled) {
3082 weaponmissdelay = .6;
3085 if (!Tutorial::active) {
3086 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3087 weapons[weaponids[weaponactive]].bloody = 1;
3089 weapons[weaponids[weaponactive]].blooddrip += 3;
3092 XYZ footvel, footpoint;
3094 if (skeleton.free) {
3095 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3097 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3099 if (Tutorial::active) {
3100 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
3103 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
3105 footvel = DoRotation(facing, 0, 90, 0) * .8;
3106 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3107 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3108 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3109 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3111 victim->DoDamage(damagemult * 0);
3115 if (animCurrent == swordslashanim && currentFrame().label == 5 && victim->animTarget != rollanim) {
3116 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
3117 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
3118 award_bonus(id, Slashbonus);
3120 if (!Tutorial::active) {
3121 if (normaldotproduct(victim->facing, victim->coords - coords) < 0) {
3122 victim->DoBloodBig(2 / victim->armorhigh, 190);
3124 victim->DoBloodBig(2 / victim->armorhigh, 185);
3126 victim->deathbleeding = 1;
3127 emit_sound_at(swordslicesound, victim->coords);
3128 victim->frameTarget = 0;
3129 victim->animTarget = staggerbackhardanim;
3130 victim->targetyaw = targetyaw + 180;
3132 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3133 weapons[weaponids[weaponactive]].bloody = 1;
3135 weapons[weaponids[weaponactive]].blooddrip += 3;
3137 float bloodlossamount;
3138 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
3139 victim->bloodloss += bloodlossamount / victim->armorhigh;
3140 victim->DoDamage(damagemult * 0);
3142 XYZ footvel, footpoint;
3144 if (skeleton.free) {
3145 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3147 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3150 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3152 footvel = DoRotation(facing, 0, 90, 0) * .8;
3154 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3155 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3156 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3157 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3160 if (victim->weaponactive != -1) {
3161 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3162 if (weapons[victim->weaponids[0]].getType() == staff) {
3163 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3165 if (weapons[weaponids[0]].getType() == staff) {
3166 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3169 emit_sound_at(swordstaffsound, victim->coords);
3171 emit_sound_at(metalhitsound, victim->coords);
3176 victim->Puff(righthand);
3178 victim->frameTarget = 0;
3179 victim->animTarget = staggerbackhighanim;
3180 victim->targetyaw = targetyaw + 180;
3182 aim = DoRotation(facing, 0, 90, 0) * 21;
3184 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3185 victim->num_weapons--;
3186 if (victim->num_weapons) {
3187 victim->weaponids[0] = victim->weaponids[num_weapons];
3188 if (victim->weaponstuck == victim->num_weapons) {
3189 victim->weaponstuck = 0;
3192 victim->weaponactive = -1;
3193 for (unsigned i = 0; i < Person::players.size(); i++) {
3194 Person::players[i]->wentforweapon = 0;
3200 if (animCurrent == staffhitanim && currentFrame().label == 5 && victim->animTarget != rollanim) {
3201 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3202 if (!Tutorial::active) {
3203 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3208 if (Random() % 2 || creature == wolftype) {
3211 emit_sound_at(staffheadsound, victim->coords);
3215 relative = victim->coords - coords;
3217 Normalise(&relative);
3218 relative = DoRotation(relative, 0, 90, 0);
3220 Normalise(&relative);
3221 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3222 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3224 victim->jointVel(head) += relative * damagemult * 230;
3225 victim->jointVel(neck) += relative * damagemult * 230;
3227 if (!Tutorial::active) {
3228 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3230 award_bonus(id, solidhit, 30);
3235 if (animCurrent == staffspinhitanim && currentFrame().label == 5 && victim->animTarget != rollanim) {
3236 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3237 if (!Tutorial::active) {
3238 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3243 if (Random() % 2 || creature == wolftype) {
3246 emit_sound_at(staffheadsound, victim->coords);
3250 relative = victim->coords - coords;
3252 Normalise(&relative);
3253 relative = DoRotation(relative, 0, -90, 0);
3254 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3255 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3257 victim->jointVel(head) += relative * damagemult * 220;
3258 victim->jointVel(neck) += relative * damagemult * 220;
3260 if (!Tutorial::active) {
3261 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3263 award_bonus(id, solidhit, 60);
3268 if (animCurrent == staffgroundsmashanim && currentFrame().label == 5) {
3269 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3271 if (!Tutorial::active) {
3272 if (!victim->dead) {
3273 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3278 if (Random() % 2 || creature == wolftype) {
3281 emit_sound_at(staffbodysound, victim->coords);
3283 victim->skeleton.longdead = 0;
3284 victim->skeleton.free = 1;
3285 victim->skeleton.broken = 0;
3287 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3288 victim->skeleton.joints[i].velchange = 0;
3289 victim->skeleton.joints[i].locked = 0;
3290 //victim->skeleton.joints[i].velocity=0;
3297 Normalise(&relative);
3298 if (!victim->dead) {
3299 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3300 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3302 victim->jointVel(abdomen) += relative * damagemult * 40;
3305 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3306 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3309 victim->Puff(abdomen);
3310 if (!Tutorial::active) {
3311 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3313 if (!victim->dead) {
3314 award_bonus(id, solidhit, 40);
3320 if (animCurrent == lowkickanim && currentFrame().label == 5) {
3321 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3327 relative = victim->coords - coords;
3329 Normalise(&relative);
3333 if (Animation::animations[victim->animTarget].height == lowheight) {
3339 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3340 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3342 victim->jointVel(head) += relative * damagemult * 200;
3343 if (!Tutorial::active) {
3344 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3347 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3348 if (victim->howactive == typesleeping) {
3349 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3351 if (creature == wolftype) {
3352 emit_sound_at(clawslicesound, victim->coords, 128.);
3354 victim->DoBloodBig(2 / victim->armorhead, 175);
3357 if (victim->damage >= victim->damagetolerance) {
3360 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3361 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3363 victim->jointVel(abdomen) += relative * damagemult * 200;
3364 victim->frameTarget = 0;
3365 victim->animTarget = staggerbackhighanim;
3366 victim->targetyaw = targetyaw + 180;
3368 if (!Tutorial::active) {
3369 emit_sound_at(landsound2, victim->coords, 128.);
3371 victim->Puff(abdomen);
3372 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3373 if (creature == wolftype) {
3374 emit_sound_at(clawslicesound, victim->coords, 128.);
3376 victim->DoBloodBig(2 / victim->armorhigh, 170);
3382 if (animCurrent == sweepanim && currentFrame().label == 5) {
3383 if ((victim->animTarget != jumpupanim) &&
3384 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3385 (victim != this->shared_from_this())) {
3390 if (!Tutorial::active) {
3391 emit_sound_at(landsound2, victim->coords, 128.);
3394 relative = victim->coords - coords;
3396 Normalise(&relative);
3398 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3401 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3402 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3404 relative = DoRotation(relative, 0, -90, 0);
3406 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3407 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) {
3408 victim->skeleton.joints[i].velocity = relative * 80;
3411 victim->Puff(rightankle);
3412 victim->Puff(leftankle);
3413 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3415 if (victim->damage >= victim->damagetolerance) {
3418 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3419 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3421 relative = DoRotation(relative, 0, -90, 0);
3422 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3423 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) {
3424 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3427 victim->jointVel(abdomen) += relative * damagemult * 200;
3428 victim->frameTarget = 0;
3429 victim->animTarget = staggerbackhighanim;
3430 victim->targetyaw = targetyaw + 180;
3432 if (!Tutorial::active) {
3433 emit_sound_at(landsound2, victim->coords, 128.);
3435 victim->Puff(abdomen);
3436 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3443 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3444 if (animCurrent == spinkickreversalanim && currentFrame().label == 7) {
3453 if (!Tutorial::active) {
3454 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3456 if (creature == wolftype) {
3457 emit_sound_at(clawslicesound, victim->coords, 128);
3459 victim->DoBloodBig(2 / victim->armorhigh, 170);
3463 relative = victim->coords - oldcoords;
3465 Normalise(&relative);
3466 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3467 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3469 victim->jointVel(abdomen) += relative * damagemult * 200;
3470 victim->Puff(abdomen);
3471 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3473 award_bonus(id, Reversal);
3476 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3477 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3478 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3479 takeWeapon(victim->weaponids[victim->weaponactive]);
3480 victim->num_weapons--;
3481 if (victim->num_weapons > 0) {
3482 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3484 victim->weaponactive = -1;
3489 if (animCurrent == staffhitreversalanim && currentFrame().label == 5) {
3498 emit_sound_at(whooshhitsound, victim->coords, 128.);
3501 relative = victim->coords - oldcoords;
3503 Normalise(&relative);
3504 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3505 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3507 victim->jointVel(abdomen) += relative * damagemult * 200;
3509 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3512 if (animCurrent == staffspinhitreversalanim && currentFrame().label == 7) {
3522 award_bonus(id, staffreversebonus);
3524 if (!Tutorial::active) {
3525 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3528 award_bonus(id, staffreversebonus); // Huh, again?
3531 relative = victim->coords - oldcoords;
3533 Normalise(&relative);
3534 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3535 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3537 victim->jointVel(abdomen) += relative * damagemult * 200;
3539 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3542 if (animCurrent == upunchreversalanim && currentFrame().label == 7) {
3548 Normalise(&relative);
3550 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3551 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3553 victim->jointVel(lefthand) *= .1;
3554 victim->jointVel(leftwrist) *= .2;
3555 victim->jointVel(leftelbow) *= .5;
3556 victim->jointVel(leftshoulder) *= .7;
3557 victim->jointVel(righthand) *= .1;
3558 victim->jointVel(rightwrist) *= .2;
3559 victim->jointVel(rightelbow) *= .5;
3560 victim->jointVel(rightshoulder) *= .7;
3562 victim->Puff(abdomen);
3563 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3565 award_bonus(id, Reversal);
3569 if (weaponactive != -1 || creature == wolftype) {
3572 if (creature == rabbittype && weaponactive != -1) {
3573 if (weapons[weaponids[0]].getType() == staff) {
3578 if (weaponactive != -1) {
3579 victim->DoBloodBig(2 / victim->armorhigh, 225);
3580 emit_sound_at(knifeslicesound, victim->coords);
3581 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3582 weapons[weaponids[weaponactive]].bloody = 1;
3584 weapons[weaponids[weaponactive]].blooddrip += 3;
3586 if (weaponactive == -1 && creature == wolftype) {
3587 emit_sound_at(clawslicesound, victim->coords, 128.);
3589 victim->DoBloodBig(2 / victim->armorhigh, 175);
3594 if (animCurrent == swordslashreversalanim && currentFrame().label == 7) {
3600 Normalise(&relative);
3602 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3603 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3605 victim->jointVel(lefthand) *= .1 - 1;
3606 victim->jointVel(leftwrist) *= .2 - 1;
3607 victim->jointVel(leftelbow) *= .5 - 1;
3608 victim->jointVel(leftshoulder) *= .7 - 1;
3609 victim->jointVel(righthand) *= .1 - 1;
3610 victim->jointVel(rightwrist) *= .2 - 1;
3611 victim->jointVel(rightelbow) *= .5 - 1;
3612 victim->jointVel(rightshoulder) *= .7 - 1;
3614 award_bonus(id, swordreversebonus);
3617 if (hasvictim && animCurrent == knifeslashreversalanim && currentFrame().label == 7) {
3626 if (!Tutorial::active) {
3627 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3631 relative = victim->coords - oldcoords;
3633 Normalise(&relative);
3634 relative = DoRotation(relative, 0, -90, 0);
3635 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3636 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3638 victim->jointVel(abdomen) += relative * damagemult * 200;
3639 victim->Puff(abdomen);
3640 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3642 award_bonus(id, Reversal);
3645 if (hasvictim && animCurrent == sneakattackanim && currentFrame().label == 7) {
3648 victim->skeleton.spinny = 0;
3650 relative = facing * -1;
3652 Normalise(&relative);
3653 if (victim->id == 0) {
3656 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3657 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3659 victim->damage = victim->damagetolerance;
3660 victim->permanentdamage = victim->damagetolerance - 1;
3663 if (weaponactive != -1 || creature == wolftype) {
3666 if (creature == rabbittype && weaponactive != -1) {
3667 if (weapons[weaponids[0]].getType() == staff) {
3672 if (weaponactive != -1) {
3673 victim->DoBloodBig(200, 225);
3674 emit_sound_at(knifeslicesound, victim->coords);
3676 weapons[weaponids[weaponactive]].bloody = 2;
3678 weapons[weaponids[weaponactive]].blooddrip += 5;
3681 if (creature == wolftype && weaponactive == -1) {
3682 emit_sound_at(clawslicesound, victim->coords, 128.);
3684 victim->DoBloodBig(2, 175);
3687 award_bonus(id, spinecrusher);
3690 if (hasvictim && (animCurrent == knifefollowanim || animCurrent == knifesneakattackanim) && currentFrame().label == 5) {
3691 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3693 if (animTarget == knifefollowanim) {
3694 victim->DoBloodBig(200, 210);
3696 if (animTarget == knifesneakattackanim) {
3697 XYZ footvel, footpoint;
3699 footpoint = weapons[weaponids[0]].tippoint;
3701 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3703 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3704 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3705 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3706 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3707 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3708 victim->DoBloodBig(200, 195);
3709 award_bonus(id, tracheotomy);
3711 if (animTarget == knifefollowanim) {
3712 award_bonus(id, Stabbonus);
3713 XYZ footvel, footpoint;
3715 footpoint = weapons[weaponids[0]].tippoint;
3717 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3719 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3720 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3721 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3722 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3723 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3725 victim->bloodloss += 10000;
3726 victim->velocity = 0;
3727 emit_sound_at(fleshstabsound, victim->coords);
3729 weapons[weaponids[weaponactive]].bloody = 2;
3731 weapons[weaponids[weaponactive]].blooddrip += 5;
3735 if (hasvictim && (animCurrent == knifefollowanim || animCurrent == knifesneakattackanim) && currentFrame().label == 6) {
3737 victim->velocity = 0;
3738 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3739 victim->skeleton.joints[i].velocity = 0;
3741 if (animTarget == knifefollowanim) {
3743 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3744 victim->skeleton.joints[i].velocity = 0;
3747 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3748 emit_sound_at(fleshstabremovesound, victim->coords);
3750 weapons[weaponids[weaponactive]].bloody = 2;
3752 weapons[weaponids[weaponactive]].blooddrip += 5;
3754 XYZ footvel, footpoint;
3756 footpoint = weapons[weaponids[0]].tippoint;
3758 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3760 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3761 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3762 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3763 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3764 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3768 if (hasvictim && (animCurrent == swordsneakattackanim) && currentFrame().label == 5) {
3769 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3770 award_bonus(id, backstab);
3774 XYZ footvel, footpoint;
3776 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3778 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3780 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3781 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3782 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3783 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3784 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3785 victim->DoBloodBig(200, 180);
3786 victim->DoBloodBig(200, 215);
3787 victim->bloodloss += 10000;
3788 victim->velocity = 0;
3789 emit_sound_at(fleshstabsound, victim->coords);
3791 weapons[weaponids[weaponactive]].bloody = 2;
3793 weapons[weaponids[weaponactive]].blooddrip += 5;
3797 if (hasvictim && animCurrent == swordsneakattackanim && currentFrame().label == 6) {
3799 victim->velocity = 0;
3800 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3801 victim->skeleton.joints[i].velocity = 0;
3803 if (weaponactive != -1) {
3804 emit_sound_at(fleshstabremovesound, victim->coords);
3806 weapons[weaponids[weaponactive]].bloody = 2;
3808 weapons[weaponids[weaponactive]].blooddrip += 5;
3810 XYZ footvel, footpoint;
3812 footpoint = weapons[weaponids[0]].tippoint;
3814 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3816 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3817 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3818 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3819 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3820 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3824 if (animCurrent == sweepreversalanim && currentFrame().label == 7) {
3833 if (weaponactive == -1) {
3834 if (!Tutorial::active) {
3835 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3840 if (weaponactive != -1 || creature == wolftype) {
3843 if (creature == rabbittype && weaponactive != -1) {
3844 if (weapons[weaponids[0]].getType() == staff) {
3849 if (weaponactive != -1) {
3850 victim->DoBloodBig(2 / victim->armorhead, 225);
3851 emit_sound_at(knifeslicesound, victim->coords);
3852 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3853 weapons[weaponids[weaponactive]].bloody = 1;
3855 weapons[weaponids[weaponactive]].blooddrip += 3;
3857 if (weaponactive == -1 && creature == wolftype) {
3858 emit_sound_at(clawslicesound, victim->coords, 128.);
3860 victim->DoBloodBig(2 / victim->armorhead, 175);
3864 award_bonus(id, Reversal);
3869 relative = facing * -1;
3871 Normalise(&relative);
3872 relative = DoRotation(relative, 0, 90, 0);
3874 Normalise(&relative);
3875 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3876 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3878 victim->jointVel(head) += relative * damagemult * 200;
3879 if (victim->damage < victim->damagetolerance - 100) {
3880 victim->velocity = relative * 200;
3882 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3883 victim->velocity = 0;
3886 if (animCurrent == sweepreversalanim && ((currentFrame().label == 9 && victim->damage < victim->damagetolerance) || (currentFrame().label == 7 && victim->damage > victim->damagetolerance))) {
3890 relative = facing * -1;
3892 Normalise(&relative);
3893 relative = DoRotation(relative, 0, 90, 0);
3895 Normalise(&relative);
3896 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3897 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3899 victim->jointVel(head) += relative * damagemult * 200;
3902 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim)) {
3903 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3904 award_bonus(id, reverseko);
3910 if (frameTarget >= int(Animation::animations[animCurrent].frames.size())) {
3913 animTarget = getIdle();
3914 FootLand(leftfoot, 1);
3915 FootLand(rightfoot, 1);
3917 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3918 animTarget = rollanim;
3920 emit_sound_at(movewhooshsound, coords, 128.);
3922 if (animCurrent == staggerbackhighanim) {
3923 animTarget = getIdle();
3925 if (animCurrent == staggerbackhardanim) {
3926 animTarget = getIdle();
3928 if (animCurrent == removeknifeanim) {
3929 animTarget = getIdle();
3931 if (animCurrent == crouchremoveknifeanim) {
3932 animTarget = getCrouch();
3934 if (animCurrent == backhandspringanim) {
3935 animTarget = getIdle();
3937 if (animCurrent == dodgebackanim) {
3938 animTarget = getIdle();
3940 if (animCurrent == drawleftanim) {
3941 animTarget = getIdle();
3943 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3944 animTarget = getIdle();
3945 if (animCurrent == crouchdrawrightanim) {
3946 animTarget = getCrouch();
3948 if (weaponactive == -1) {
3950 } else if (weaponactive == 0) {
3952 if (num_weapons == 2) {
3954 buffer = weaponids[0];
3955 weaponids[0] = weaponids[1];
3956 weaponids[1] = buffer;
3960 if (weaponactive == -1) {
3961 emit_sound_at(knifesheathesound, coords, 128.);
3963 if (weaponactive != -1) {
3964 emit_sound_at(knifedrawsound, coords, 128.);
3967 if (animCurrent == rollanim) {
3968 animTarget = getCrouch();
3969 FootLand(leftfoot, 1);
3970 FootLand(rightfoot, 1);
3973 if (animTarget == walljumprightkickanim) {
3976 if (animTarget == walljumpleftkickanim) {
3979 animTarget = jumpdownanim;
3981 if (animCurrent == climbanim) {
3982 animTarget = getCrouch();
3984 coords += facing * .1;
3985 if (!isnormal(coords.x)) {
3996 if (animTarget == rabbitkickreversalanim) {
3997 animTarget = getCrouch();
4000 if (animTarget == jumpreversalanim) {
4001 animTarget = getCrouch();
4004 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
4005 if (attackkeydown && animTarget != walljumpfrontanim) {
4007 float closestdist = -1;
4009 if (Person::players.size() > 1) {
4010 for (unsigned i = 0; i < Person::players.size(); i++) {
4011 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4012 distance = distsq(&Person::players[i]->coords, &coords);
4013 if (closestdist == -1 || distance < closestdist) {
4014 closestdist = distance;
4020 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4021 victim = Person::players[closest];
4022 animTarget = walljumprightkickanim;
4024 XYZ rotatetarget = victim->coords - coords;
4025 Normalise(&rotatetarget);
4026 yaw = -asin(0 - rotatetarget.x);
4028 if (rotatetarget.z < 0) {
4031 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4032 velocity = (victim->coords - coords) * 4;
4037 if (animTarget == walljumpbackanim) {
4038 animTarget = backflipanim;
4040 velocity = facing * -8;
4043 resume_stream(whooshsound);
4046 if (animTarget == walljumprightanim) {
4047 animTarget = rightflipanim;
4051 velocity = DoRotation(facing, 0, 30, 0) * -8;
4054 if (animTarget == walljumpfrontanim) {
4055 animTarget = frontflipanim;
4059 velocity = facing * 8;
4063 resume_stream(whooshsound);
4066 if (animTarget == walljumpleftanim) {
4067 if (attackkeydown) {
4069 float closestdist = -1;
4071 if (Person::players.size() > 1) {
4072 for (unsigned i = 0; i < Person::players.size(); i++) {
4073 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4074 distance = distsq(&Person::players[i]->coords, &coords);
4075 if (closestdist == -1 || distance < closestdist) {
4076 closestdist = distance;
4082 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4083 victim = Person::players[closest];
4084 animTarget = walljumpleftkickanim;
4086 XYZ rotatetarget = victim->coords - coords;
4087 Normalise(&rotatetarget);
4088 yaw = -asin(0 - rotatetarget.x);
4090 if (rotatetarget.z < 0) {
4093 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4094 velocity = (victim->coords - coords) * 4;
4099 if (animTarget != walljumpleftkickanim) {
4100 animTarget = leftflipanim;
4104 velocity = DoRotation(facing, 0, -30, 0) * -8;
4108 resume_stream(whooshsound);
4111 if (animTarget == sneakattackanim) {
4112 animCurrent = getCrouch();
4113 animTarget = getCrouch();
4120 transspeed = 1000000;
4121 targetheadyaw += 180;
4122 coords -= facing * .7;
4124 coords.y = terrain.getHeight(coords.x, coords.z);
4129 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
4130 animTarget = getIdle();
4133 coords.y = terrain.getHeight(coords.x, coords.z);
4138 if (animCurrent == knifefollowanim) {
4139 animTarget = getIdle();
4142 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
4143 float ycoords = oldcoords.y;
4144 animTarget = getStop();
4149 transspeed = 1000000;
4150 targetheadyaw += 180;
4151 if (!isnormal(coords.x)) {
4154 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim) {
4155 oldcoords = coords + facing * .5;
4156 } else if (animCurrent == sweepreversalanim) {
4157 oldcoords = coords + facing * 1.1;
4158 } else if (animCurrent == upunchreversalanim) {
4159 oldcoords = coords + facing * 1.5;
4162 targetheadyaw += 180;
4165 } else if (animCurrent == knifeslashreversalanim) {
4166 oldcoords = coords + facing * .5;
4169 targetheadyaw += 90;
4172 } else if (animCurrent == staffspinhitreversalanim) {
4175 targetheadyaw += 180;
4180 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
4182 oldcoords.y = ycoords;
4184 currentoffset = coords - oldcoords;
4190 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4195 if (Animation::animations[animTarget].attack == reversed) {
4197 if (animTarget == sweepreversedanim) {
4200 animTarget = backhandspringanim;
4202 emit_sound_at(landsound, coords, 128);
4204 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4205 animTarget = rollanim;
4208 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4209 coords.y = oldcoords.y;
4211 if (animCurrent == knifeslashreversedanim) {
4212 animTarget = rollanim;
4217 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4218 coords.y = oldcoords.y;
4222 animTarget = jumpdownanim;
4225 animTarget = getIdle();
4227 if (wasLandhard()) {
4228 animTarget = getIdle();
4230 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4231 animTarget = getIdle();
4233 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4234 coords.y = oldcoords.y;
4235 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4236 targetoffset.y = coords.y;
4238 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4240 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4241 currentoffset.y -= (coords.y - targetoffset.y);
4242 coords.y = targetoffset.y;
4244 normalsupdatedelay = 0;
4246 if (animCurrent == upunchanim) {
4247 animTarget = getStop();
4248 normalsupdatedelay = 0;
4251 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4255 if (num_weapons > 0) {
4256 if (weapons[0].getType() == staff) {
4265 rabbitkickragdoll = 1;
4267 if (animCurrent == rabbitkickreversedanim) {
4273 skeleton.spinny = 0;
4274 SolidHitBonus(!id); // FIXME: tricky id
4278 animTarget = rollanim;
4281 pause_sound(whooshsound);
4286 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4290 skeleton.spinny = 0;
4292 if (animCurrent == jumpreversedanim) {
4298 skeleton.spinny = 0;
4299 SolidHitBonus(!id); // FIXME: tricky id
4303 animTarget = rollanim;
4304 coords += facing * 2;
4306 pause_sound(whooshsound);
4312 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) {
4313 animTarget = getupfromfrontanim;
4315 } else if (Animation::animations[animCurrent].attack == normalattack) {
4316 animTarget = getIdle();
4319 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4320 animTarget = blockhighleftstrikeanim;
4322 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4323 animTarget = getIdle();
4326 if (animCurrent == spinkickanim && victim->skeleton.free) {
4327 if (creature == rabbittype) {
4328 animTarget = fightidleanim;
4334 if (isIdle() && !wasIdle()) {
4335 normalsupdatedelay = 0;
4338 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4339 animTarget = jumpdownanim;
4342 if (!skeleton.free) {
4344 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4345 if (!isRun() || !wasRun()) {
4346 if (targetFrame().speed > currentFrame().speed) {
4347 target += multiplier * targetFrame().speed * speed * 2;
4349 if (targetFrame().speed <= currentFrame().speed) {
4350 target += multiplier * currentFrame().speed * speed * 2;
4353 if (isRun() && wasRun()) {
4355 tempspeed = velspeed;
4356 if (tempspeed < 10 * speedmult) {
4357 tempspeed = 10 * speedmult;
4359 /* FIXME - mixed of target and current here, is that intended? */
4360 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4362 } else if (transspeed) {
4363 target += multiplier * transspeed * speed * 2;
4365 if (!isRun() || !wasRun()) {
4366 if (targetFrame().speed > currentFrame().speed) {
4367 target += multiplier * targetFrame().speed * 2;
4369 if (targetFrame().speed <= currentFrame().speed) {
4370 target += multiplier * currentFrame().speed * 2;
4375 if (animCurrent != animTarget) {
4376 target = (target + oldtarget) / 2;
4380 frameCurrent = frameTarget;
4384 if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
4385 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4389 rot = targetrot * target;
4390 yaw += rot - oldrot;
4397 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4399 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4400 skeleton.joints[i].position = currentFrame().joints[i].position;
4403 skeleton.FindForwards();
4405 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4406 if (skeleton.muscles[i].visible) {
4407 skeleton.FindRotationMuscle(i, animTarget);
4410 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4411 if (skeleton.muscles[i].visible) {
4412 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4413 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4415 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4416 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4418 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4419 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4425 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4426 skeleton.joints[i].position = targetFrame().joints[i].position;
4429 skeleton.FindForwards();
4431 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4432 if (skeleton.muscles[i].visible) {
4433 skeleton.FindRotationMuscle(i, animTarget);
4436 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4437 if (skeleton.muscles[i].visible) {
4438 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4439 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4441 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4442 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4444 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4445 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4447 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) {
4448 skeleton.muscles[i].newrotate3 -= 360;
4450 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) {
4451 skeleton.muscles[i].newrotate3 += 360;
4453 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) {
4454 skeleton.muscles[i].newrotate2 -= 360;
4456 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) {
4457 skeleton.muscles[i].newrotate2 += 360;
4459 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) {
4460 skeleton.muscles[i].newrotate1 -= 360;
4462 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) {
4463 skeleton.muscles[i].newrotate1 += 360;
4469 oldanimCurrent = animCurrent;
4470 oldanimTarget = animTarget;
4471 oldframeTarget = frameTarget;
4472 oldframeCurrent = frameCurrent;
4474 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4475 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target - skeleton.joints[i].position) / multiplier;
4476 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target;
4478 offset = currentoffset * (1 - target) + targetoffset * target;
4479 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4480 if (skeleton.muscles[i].visible) {
4481 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * target;
4482 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * target;
4483 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * target;
4488 if (isLanding() && landhard) {
4492 animTarget = getLandhard();
4505 void Person::DoStuff()
4507 static XYZ terrainnormal;
4508 static XYZ flatfacing;
4509 static XYZ flatvelocity;
4510 static float flatvelspeed;
4511 static int bloodsize;
4512 static int startx, starty, endx, endy;
4513 static GLubyte color;
4514 static XYZ bloodvel;
4516 onfiredelay -= multiplier;
4517 if (onfiredelay < 0 && onfire) {
4518 if (Random() % 2 == 0) {
4524 crouchkeydowntime += multiplier;
4525 if (!crouchkeydown) {
4526 crouchkeydowntime = 0;
4528 jumpkeydowntime += multiplier;
4529 if (!jumpkeydown && skeleton.free) {
4530 jumpkeydowntime = 0;
4533 if (hostile || damage > 0 || bloodloss > 0) {
4537 if (isIdle() || isRun()) {
4541 if (num_weapons == 1 && weaponactive != -1) {
4546 blooddimamount -= multiplier * .3;
4548 speechdelay -= multiplier;
4549 texupdatedelay -= multiplier;
4550 interestdelay -= multiplier;
4551 flamedelay -= multiplier;
4552 parriedrecently -= multiplier;
4554 victim = this->shared_from_this();
4559 speed = 1.1 * speedmult;
4561 speed = 1.0 * speedmult;
4563 if (!skeleton.free) {
4564 rabbitkickragdoll = 0;
4569 if (id != 0 && (creature == rabbittype || difficulty != 2)) {
4572 if (id != 0 && creature == wolftype && difficulty == 2) {
4574 if (aitype != passivetype) {
4576 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) {
4583 if (animTarget == wolfrunninganim && !superruntoggle) {
4584 animTarget = getRun();
4588 if (weaponactive == -1 && num_weapons > 0) {
4589 if (weapons[weaponids[0]].getType() == staff) {
4595 burnt += multiplier;
4600 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4602 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4609 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
4610 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4614 while (flamedelay < 0 && onfire) {
4616 int howmany = fabs(Random() % (skeleton.joints.size()));
4617 if (skeleton.free) {
4618 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4619 flatfacing = skeleton.joints[howmany].position * scale + coords;
4621 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4622 flatvelocity = (coords - oldcoords) / multiplier / 2;
4624 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4627 while (flamedelay < 0 && !onfire && Tutorial::active && id != 0) {
4629 int howmany = fabs(Random() % (skeleton.joints.size()));
4630 if (skeleton.free) {
4631 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4632 flatfacing = skeleton.joints[howmany].position * scale + coords;
4634 flatvelocity = (coords - oldcoords) / multiplier / 2;
4635 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4637 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4641 bleeding -= multiplier * .3;
4642 if (bloodtoggle == 2) {
4643 skeleton.drawmodel.textureptr.bind();
4644 if ((bleeding <= 0) && (detail != 2)) {
4650 if (neckspurtamount > 0) {
4651 neckspurtamount -= multiplier;
4652 neckspurtdelay -= multiplier * 3;
4653 neckspurtparticledelay -= multiplier * 3;
4654 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4657 if (skeleton.free) {
4658 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4659 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4660 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4662 bloodvel.z = 5 * neckspurtamount;
4663 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4664 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4665 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4667 neckspurtparticledelay = .05;
4669 if (neckspurtdelay < 0) {
4674 if (deathbleeding > 0 && dead != 2) {
4675 if (deathbleeding < 5) {
4676 bleeddelay -= deathbleeding * multiplier / 4;
4678 bleeddelay -= 5 * multiplier / 4;
4680 if (bleeddelay < 0 && bloodtoggle) {
4685 if (skeleton.free) {
4686 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4687 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4689 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4690 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4694 bloodloss += deathbleeding * multiplier * 80;
4695 deathbleeding -= multiplier * 1.6;
4696 if (deathbleeding < 0) {
4699 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4700 if (weaponactive != -1) {
4701 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4702 weapons[weaponids[0]].velocity.x += .01;
4705 weaponids[0] = weaponids[num_weapons];
4706 if (weaponstuck == num_weapons) {
4711 for (unsigned i = 0; i < Person::players.size(); i++) {
4712 Person::players[i]->wentforweapon = 0;
4720 if (!dead && creature == wolftype) {
4721 award_bonus(0, Wolfbonus);
4724 if (animTarget == knifefollowedanim && !skeleton.free) {
4725 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4726 skeleton.joints[i].velocity = 0;
4727 skeleton.joints[i].velocity.y = -2;
4730 if (id != 0 && unconscioustime > .1) {
4738 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4739 texupdatedelay = .12;
4741 bloodsize = 5 - realtexdetail;
4745 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4746 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4747 endx = startx + bloodsize;
4748 endy = starty + bloodsize;
4758 if (endx > skeleton.skinsize - 1) {
4759 endx = skeleton.skinsize - 1;
4762 if (endy > skeleton.skinsize - 1) {
4763 endy = skeleton.skinsize - 1;
4766 if (endx < startx) {
4769 if (endy < starty) {
4773 for (int i = startx; i < endx; i++) {
4774 for (int j = starty; j < endy; j++) {
4775 if (Random() % 2 == 0) {
4776 color = Random() % 85 + 170;
4777 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2) {
4778 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4780 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4781 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4786 skeleton.drawmodel.textureptr.bind();
4790 if (skeleton.free) {
4791 bleedx += 4 * direction / realtexdetail;
4793 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4795 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4798 bleedy -= 4 / realtexdetail;
4800 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4802 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4807 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4808 righthandmorphness = targetrighthandmorphness;
4809 righthandmorphstart = righthandmorphend;
4810 } else if (righthandmorphness > targetrighthandmorphness) {
4811 righthandmorphness -= multiplier * 4;
4812 } else if (righthandmorphness < targetrighthandmorphness) {
4813 righthandmorphness += multiplier * 4;
4816 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4817 lefthandmorphness = targetlefthandmorphness;
4818 lefthandmorphstart = lefthandmorphend;
4819 } else if (lefthandmorphness > targetlefthandmorphness) {
4820 lefthandmorphness -= multiplier * 4;
4821 } else if (lefthandmorphness < targetlefthandmorphness) {
4822 lefthandmorphness += multiplier * 4;
4825 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4826 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4827 tailmorphness = targettailmorphness;
4828 tailmorphstart = tailmorphend;
4829 } else if (tailmorphness > targettailmorphness) {
4830 tailmorphness -= multiplier * 10;
4831 } else if (tailmorphness < targettailmorphness) {
4832 tailmorphness += multiplier * 10;
4836 if (creature == wolftype) {
4837 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4838 tailmorphness = targettailmorphness;
4839 tailmorphstart = tailmorphend;
4840 } else if (tailmorphness > targettailmorphness) {
4841 tailmorphness -= multiplier * 2;
4842 } else if (tailmorphness < targettailmorphness) {
4843 tailmorphness += multiplier * 2;
4847 if (headmorphend == 3 || headmorphstart == 3) {
4848 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4849 headmorphness = targetheadmorphness;
4850 headmorphstart = headmorphend;
4851 } else if (headmorphness > targetheadmorphness) {
4852 headmorphness -= multiplier * 7;
4853 } else if (headmorphness < targetheadmorphness) {
4854 headmorphness += multiplier * 7;
4856 } else if (headmorphend == 5 || headmorphstart == 5) {
4857 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4858 headmorphness = targetheadmorphness;
4859 headmorphstart = headmorphend;
4860 } else if (headmorphness > targetheadmorphness) {
4861 headmorphness -= multiplier * 10;
4862 } else if (headmorphness < targetheadmorphness) {
4863 headmorphness += multiplier * 10;
4866 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4867 headmorphness = targetheadmorphness;
4868 headmorphstart = headmorphend;
4869 } else if (headmorphness > targetheadmorphness) {
4870 headmorphness -= multiplier * 4;
4871 } else if (headmorphness < targetheadmorphness) {
4872 headmorphness += multiplier * 4;
4876 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4877 chestmorphness = targetchestmorphness;
4878 chestmorphstart = chestmorphend;
4879 } else if (chestmorphness > targetchestmorphness) {
4880 chestmorphness -= multiplier;
4881 } else if (chestmorphness < targetchestmorphness) {
4882 chestmorphness += multiplier;
4885 if (dead != 2 && howactive <= typesleeping) {
4886 if (chestmorphstart == 0 && chestmorphend == 0) {
4888 targetchestmorphness = 1;
4891 if (chestmorphstart != 0 && chestmorphend != 0) {
4893 targetchestmorphness = 1;
4895 if (environment == snowyenvironment) {
4898 if (skeleton.free) {
4899 footvel = skeleton.specialforward[0] * -1;
4900 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4902 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4903 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4905 if (animTarget == sleepanim) {
4906 footvel = DoRotation(footvel, 0, 90, 0);
4908 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4912 if (!dead && howactive < typesleeping) {
4913 blinkdelay -= multiplier * 2;
4914 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4916 targetheadmorphness = 1;
4918 blinkdelay = (float)(abs(Random() % 40)) / 5;
4920 if (headmorphstart == 3 && headmorphend == 3) {
4922 targetheadmorphness = 1;
4927 twitchdelay -= multiplier * 1.5;
4928 if (animTarget != hurtidleanim) {
4929 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4931 targetheadmorphness = 1;
4933 twitchdelay = (float)(abs(Random() % 40)) / 5;
4935 if (headmorphstart == 5 && headmorphend == 5) {
4937 targetheadmorphness = 1;
4941 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4942 twitchdelay3 -= multiplier * 1;
4943 if (Random() % 2 == 0) {
4944 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4945 righthandmorphness = 0;
4946 targetrighthandmorphness = 1;
4947 righthandmorphend = 1;
4948 if (Random() % 2 == 0) {
4949 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4952 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4953 righthandmorphness = 0;
4954 targetrighthandmorphness = 1;
4955 righthandmorphend = 0;
4958 if (Random() % 2 == 0) {
4959 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4960 lefthandmorphness = 0;
4961 targetlefthandmorphness = 1;
4962 lefthandmorphend = 1;
4963 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4965 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4966 lefthandmorphness = 0;
4967 targetlefthandmorphness = 1;
4968 lefthandmorphend = 0;
4974 if (creature == rabbittype) {
4975 if (howactive < typesleeping) {
4976 twitchdelay2 -= multiplier * 1.5;
4978 twitchdelay2 -= multiplier * 0.5;
4980 if (howactive <= typesleeping) {
4981 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4983 targettailmorphness = 1;
4985 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4987 if (tailmorphstart == 1 && tailmorphend == 1) {
4989 targettailmorphness = 1;
4992 if (tailmorphstart == 2 && tailmorphend == 2) {
4994 targettailmorphness = 1;
5001 if (creature == wolftype) {
5002 twitchdelay2 -= multiplier * 1.5;
5003 if (tailmorphend != 0) {
5004 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
5006 targettailmorphness = 1;
5011 if (tailmorphend != 5) {
5012 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
5014 targettailmorphness = 1;
5019 if (twitchdelay2 <= 0) {
5020 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
5022 targettailmorphness = 1;
5025 if (tailmorphstart == 1 && tailmorphend == 1) {
5027 targettailmorphness = 1;
5030 if (tailmorphstart == 2 && tailmorphend == 2) {
5032 targettailmorphness = 1;
5035 if (tailmorphstart == 3 && tailmorphend == 3) {
5037 targettailmorphness = 1;
5040 if (tailmorphstart == 4 && tailmorphend == 4) {
5042 targettailmorphness = 1;
5049 unconscioustime = 0;
5052 if (dead == 1 || howactive == typesleeping) {
5053 unconscioustime += multiplier;
5054 //If unconscious, close eyes and mouth
5055 if (righthandmorphend != 0) {
5056 righthandmorphness = 0;
5058 righthandmorphend = 0;
5059 targetrighthandmorphness = 1;
5061 if (lefthandmorphend != 0) {
5062 lefthandmorphness = 0;
5064 lefthandmorphend = 0;
5065 targetlefthandmorphness = 1;
5067 if (headmorphend != 3 && headmorphend != 5) {
5071 targetheadmorphness = 1;
5074 if (howactive > typesleeping) {
5077 if (bloodtoggle && !bled) {
5078 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5079 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5080 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5081 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5085 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5091 if (dead == 2 || howactive > typesleeping) {
5092 //If dead, open mouth and hands
5093 if (righthandmorphend != 0) {
5094 righthandmorphness = 0;
5096 righthandmorphend = 0;
5097 targetrighthandmorphness = 1;
5099 if (lefthandmorphend != 0) {
5100 lefthandmorphness = 0;
5102 lefthandmorphend = 0;
5103 targetlefthandmorphness = 1;
5105 if (headmorphend != 2) {
5109 targetheadmorphness = 1;
5112 if (stunned > 0 && !dead && headmorphend != 2) {
5113 if (headmorphend != 4) {
5117 targetheadmorphness = 1;
5120 if (damage > damagetolerance && !dead) {
5123 unconscioustime = 0;
5125 if (creature == wolftype) {
5126 award_bonus(0, Wolfbonus);
5131 if (weaponactive != -1) {
5132 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5133 weapons[weaponids[0]].velocity.x += .01;
5136 weaponids[0] = weaponids[num_weapons];
5137 if (weaponstuck == num_weapons) {
5142 for (unsigned i = 0; i < Person::players.size(); i++) {
5143 Person::players[i]->wentforweapon = 0;
5147 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
5156 damage -= multiplier * 13;
5157 permanentdamage -= multiplier * 4;
5158 if (isIdle() || isCrouch()) {
5159 permanentdamage -= multiplier * 4;
5165 if (permanentdamage < 0) {
5166 permanentdamage = 0;
5168 if (superpermanentdamage < 0) {
5169 superpermanentdamage = 0;
5171 if (permanentdamage < superpermanentdamage) {
5172 permanentdamage = superpermanentdamage;
5174 if (damage < permanentdamage) {
5175 damage = permanentdamage;
5177 if (dead == 1 && damage < damagetolerance) {
5181 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5182 skeleton.joints[i].velocity = 0;
5185 if (permanentdamage > damagetolerance && dead != 2) {
5188 if (weaponactive != -1) {
5189 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5190 weapons[weaponids[0]].velocity.x += .01;
5193 weaponids[0] = weaponids[num_weapons];
5194 if (weaponstuck == num_weapons) {
5199 for (unsigned i = 0; i < Person::players.size(); i++) {
5200 Person::players[i]->wentforweapon = 0;
5206 if (!dead && creature == wolftype) {
5207 award_bonus(0, Wolfbonus);
5210 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance) {
5211 award_bonus(id, touchofdeath);
5213 if (id != 0 && unconscioustime > .1) {
5221 emit_sound_at(breaksound, coords);
5224 if (skeleton.free == 1) {
5226 pause_sound(whooshsound);
5230 //If knocked over, open hands and close mouth
5231 if (righthandmorphend != 0) {
5232 righthandmorphness = 0;
5234 righthandmorphend = 0;
5235 targetrighthandmorphness = 1;
5237 if (lefthandmorphend != 0) {
5238 lefthandmorphness = 0;
5240 lefthandmorphend = 0;
5241 targetlefthandmorphness = 1;
5243 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
5244 if (headmorphend != 0) {
5248 targetheadmorphness = 1;
5252 skeleton.DoGravity(&scale);
5254 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
5255 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1)) {
5256 award_bonus(id, deepimpact);
5258 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5262 if (!skeleton.joints.empty()) {
5263 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5264 average += skeleton.joints[j].position;
5266 average /= skeleton.joints.size();
5267 coords += average * scale;
5268 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5269 skeleton.joints[j].position -= average;
5271 average /= multiplier;
5275 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5276 velocity += skeleton.joints[i].velocity * scale;
5278 velocity /= skeleton.joints.size();
5280 if (!isnormal(velocity.x) && velocity.x) {
5284 if (findLength(&average) < 10 && dead && skeleton.free) {
5285 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5286 if (skeleton.longdead > 2000) {
5287 if (skeleton.longdead > 6000) {
5289 pause_sound(whooshsound);
5295 if (dead == 2 && bloodloss < damagetolerance) {
5297 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5299 if (bloodtoggle && !bled) {
5300 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5301 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5302 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5303 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5304 float size = .2 * 1.2;
5307 Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5312 if (dead == 2 && bloodloss >= damagetolerance) {
5314 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5315 if (bleeding <= 0) {
5318 if (bloodtoggle && !bled) {
5319 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5320 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5321 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5322 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5326 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5334 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5335 bool canrecover = 1;
5336 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5337 startpoint = coords;
5340 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1) {
5343 if (velocity.y < -30) {
5346 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5347 if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) {
5348 colviewer = startpoint;
5349 coltarget = endpoint;
5350 if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1) {
5360 terrainnormal = jointPos(groin) - jointPos(abdomen);
5361 if (joint(groin).locked && joint(abdomen).locked) {
5362 terrainnormal = jointPos(groin) - jointPos(abdomen);
5363 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5365 if (joint(abdomen).locked && joint(neck).locked) {
5366 terrainnormal = jointPos(abdomen) - jointPos(neck);
5367 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5369 if (joint(groin).locked && joint(neck).locked) {
5370 terrainnormal = jointPos(groin) - jointPos(neck);
5371 middle = (jointPos(groin) + jointPos(neck)) / 2;
5373 Normalise(&terrainnormal);
5375 targetyaw = -asin(0 - terrainnormal.x);
5376 targetyaw *= 360 / 6.28;
5377 if (terrainnormal.z < 0) {
5378 targetyaw = 180 - targetyaw;
5383 animTarget = flipanim;
5384 crouchtogglekeydown = 1;
5389 animCurrent = tempanim;
5393 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5394 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5395 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5400 if (findLength(&average) < 10 && !dead && skeleton.free) {
5401 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5402 if (skeleton.longdead > (damage + 500) * 1.5) {
5404 pause_sound(whooshsound);
5411 terrainnormal = jointPos(groin) - jointPos(abdomen);
5412 if (joint(groin).locked && joint(abdomen).locked) {
5413 terrainnormal = jointPos(groin) - jointPos(abdomen);
5414 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5416 if (joint(abdomen).locked && joint(neck).locked) {
5417 terrainnormal = jointPos(abdomen) - jointPos(neck);
5418 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5420 if (joint(groin).locked && joint(neck).locked) {
5421 terrainnormal = jointPos(groin) - jointPos(neck);
5422 middle = (jointPos(groin) + jointPos(neck)) / 2;
5424 Normalise(&terrainnormal);
5426 targetyaw = -asin(0 - terrainnormal.x);
5427 targetyaw *= 360 / 6.28;
5428 if (terrainnormal.z < 0) {
5429 targetyaw = 180 - targetyaw;
5433 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5435 if (skeleton.forward.y < 0) {
5436 animTarget = getupfrombackanim;
5440 if (skeleton.forward.y > -.3) {
5441 animTarget = getupfromfrontanim;
5449 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5450 animTarget = rollanim;
5451 targetyaw = lookyaw;
5455 if (forwardkeydown) {
5464 if (forwardkeydown) {
5472 if (!leftkeydown && !rightkeydown) {
5480 if (abs(targettilt2) > 50) {
5483 animCurrent = tempanim;
5486 tilt2 = targettilt2;
5488 if (middle.y > 0 && animTarget != rollanim) {
5489 targetoffset.y = middle.y + 1;
5492 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5493 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5494 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5501 if (num_weapons > 0) {
5502 if (weapons[0].getType() == staff) {
5506 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5507 if (velocity.y > -30) {
5509 tempvelocity = velocity;
5510 Normalise(&tempvelocity);
5511 targetyaw = -asin(0 - tempvelocity.x);
5512 targetyaw *= 360 / 6.28;
5513 if (velocity.z < 0) {
5514 targetyaw = 180 - targetyaw;
5519 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5520 animTarget = rollanim;
5523 animTarget = backhandspringanim;
5529 emit_sound_at(movewhooshsound, coords, 128.);
5531 animCurrent = animTarget;
5532 frameCurrent = frameTarget - 1;
5544 if (skeleton.freefall == 0) {
5549 if (aitype != passivetype || skeleton.free == 1) {
5550 if (findLengthfast(&velocity) > .1) {
5551 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5552 if (Object::objects[i]->type == firetype) {
5553 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) {
5555 if (!Object::objects[i]->onfire) {
5556 emit_sound_at(firestartsound, Object::objects[i]->position);
5558 Object::objects[i]->onfire = 1;
5561 if (Object::objects[i]->onfire) {
5567 if (Object::objects[i]->type == bushtype) {
5568 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) {
5570 if (!Object::objects[i]->onfire) {
5571 emit_sound_at(firestartsound, Object::objects[i]->position);
5573 Object::objects[i]->onfire = 1;
5577 if (Object::objects[i]->onfire) {
5581 if (Object::objects[i]->messedwith <= 0) {
5585 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5588 addEnvSound(coords, 4 * findLength(&velocity));
5592 if (environment == grassyenvironment) {
5593 howmany = findLength(&velocity) * 4;
5595 if (environment == snowyenvironment) {
5596 howmany = findLength(&velocity) * 2;
5599 if (environment != desertenvironment) {
5600 for (int j = 0; j < howmany; j++) {
5601 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5602 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5603 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5606 pos.x += float(abs(Random() % 100) - 50) / 200;
5607 pos.y += float(abs(Random() % 100) - 50) / 200;
5608 pos.z += float(abs(Random() % 100) - 50) / 200;
5609 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);
5610 Sprite::setLastSpriteSpecial(1);
5614 howmany = findLength(&velocity) * 4;
5616 if (environment == snowyenvironment) {
5617 for (int j = 0; j < howmany; j++) {
5618 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5619 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5620 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5623 pos.x += float(abs(Random() % 100) - 50) / 200;
5624 pos.y += float(abs(Random() % 100) - 50) / 200;
5625 pos.z += float(abs(Random() % 100) - 50) / 200;
5626 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5627 Sprite::setLastSpriteSpecial(2);
5632 Object::objects[i]->rotx += velocity.x * multiplier * 6;
5633 Object::objects[i]->roty += velocity.z * multiplier * 6;
5634 Object::objects[i]->messedwith = .5;
5638 if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) {
5639 if (Object::objects[i]->pitch == 0) {
5642 tempcoord = coords - Object::objects[i]->position;
5643 tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0);
5644 tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0);
5645 tempcoord += Object::objects[i]->position;
5647 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) {
5648 if (Object::objects[i]->messedwith <= 0) {
5652 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5655 addEnvSound(coords, 4 * findLength(&velocity));
5659 if (environment == grassyenvironment) {
5660 howmany = findLength(&velocity) * 4;
5662 if (environment == snowyenvironment) {
5663 howmany = findLength(&velocity) * 2;
5666 if (environment != desertenvironment) {
5667 for (int j = 0; j < howmany; j++) {
5668 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5669 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5670 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5672 pos += velocity * .1;
5674 pos.x += float(abs(Random() % 100) - 50) / 150;
5675 pos.y += float(abs(Random() % 100) - 50) / 150;
5676 pos.z += float(abs(Random() % 100) - 50) / 150;
5677 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);
5678 Sprite::setLastSpriteSpecial(1);
5682 howmany = findLength(&velocity) * 4;
5684 if (environment == snowyenvironment) {
5685 for (int j = 0; j < howmany; j++) {
5686 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5687 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5688 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5690 pos += velocity * .1;
5692 pos.x += float(abs(Random() % 100) - 50) / 150;
5693 pos.y += float(abs(Random() % 100) - 50) / 150;
5694 pos.z += float(abs(Random() % 100) - 50) / 150;
5695 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5696 Sprite::setLastSpriteSpecial(2);
5701 Object::objects[i]->messedwith = .5;
5708 if (!skeleton.free) {
5711 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype) {
5715 if (aitype != passivetype && victim->skeleton.free && !victim->dead) {
5719 if (Tutorial::active && id != 0) {
5722 if (play && aitype != playercontrolled) {
5723 int whichsound = -1;
5724 if (speechdelay <= 0) {
5725 unsigned int i = abs(Random() % 4);
5727 whichsound = PersonType::types[creature].soundsTalk[i];
5732 if (whichsound != -1) {
5733 emit_sound_at(whichsound, coords);
5737 if (animTarget == staggerbackhighanim) {
5740 if (animTarget == staggerbackhardanim) {
5743 staggerdelay -= multiplier;
5744 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
5747 if (velocity.y < -30 && animTarget == jumpdownanim) {
5750 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5751 animTarget = getIdle();
5755 weaponmissdelay -= multiplier;
5756 highreversaldelay -= multiplier;
5757 lowreversaldelay -= multiplier;
5758 lastcollide -= multiplier;
5759 skiddelay -= multiplier;
5760 if (!isnormal(velocity.x) && velocity.x) {
5763 if (!isnormal(targettilt) && targettilt) {
5766 if (!isnormal(targettilt2) && targettilt2) {
5769 if (!isnormal(targetyaw) && targetyaw) {
5773 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5774 //open hands and close mouth
5775 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5776 righthandmorphness = 0;
5777 righthandmorphend = 0;
5778 targetrighthandmorphness = 1;
5781 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5782 lefthandmorphness = 0;
5783 lefthandmorphend = 0;
5784 targetlefthandmorphness = 1;
5787 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5790 targetheadmorphness = 1;
5794 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) {
5795 //open hands and mouth
5796 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5797 righthandmorphness = 0;
5798 righthandmorphend = 0;
5799 targetrighthandmorphness = 1;
5802 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5803 lefthandmorphness = 0;
5804 lefthandmorphend = 0;
5805 targetlefthandmorphness = 1;
5808 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5811 targetheadmorphness = 1;
5815 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5816 //close hands and mouth
5817 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5818 righthandmorphness = 0;
5819 righthandmorphend = 1;
5820 targetrighthandmorphness = 1;
5823 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5824 lefthandmorphness = 0;
5825 lefthandmorphend = 1;
5826 targetlefthandmorphness = 1;
5829 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5832 targetheadmorphness = 1;
5836 if (animTarget == spinkickanim ||
5837 animTarget == staffspinhitreversalanim ||
5838 animTarget == staffspinhitreversedanim ||
5839 animTarget == staffhitreversalanim ||
5840 animTarget == staffhitreversedanim ||
5841 animTarget == hurtidleanim ||
5842 animTarget == winduppunchanim ||
5843 animTarget == swordslashreversalanim ||
5844 animTarget == swordslashreversedanim ||
5845 animTarget == knifeslashreversalanim ||
5846 animTarget == knifeslashreversedanim ||
5847 animTarget == knifethrowanim ||
5848 animTarget == knifefollowanim ||
5849 animTarget == knifefollowedanim ||
5850 animTarget == killanim ||
5851 animTarget == dropkickanim ||
5852 animTarget == upunchanim ||
5853 animTarget == knifeslashstartanim ||
5854 animTarget == swordslashanim ||
5855 animTarget == staffhitanim ||
5856 animTarget == staffspinhitanim ||
5857 animTarget == staffgroundsmashanim ||
5858 animTarget == spinkickreversalanim ||
5859 animTarget == sweepreversalanim ||
5860 animTarget == lowkickanim ||
5861 animTarget == sweepreversedanim ||
5862 animTarget == rabbitkickreversalanim ||
5863 animTarget == rabbitkickreversedanim ||
5864 animTarget == jumpreversalanim ||
5865 animTarget == jumpreversedanim) {
5866 //close hands and yell
5867 if (righthandmorphend != 1 &&
5868 righthandmorphness == targetrighthandmorphness) {
5869 righthandmorphness = 0;
5870 righthandmorphend = 1;
5871 targetrighthandmorphness = 1;
5874 if (lefthandmorphend != 1 &&
5875 lefthandmorphness == targetlefthandmorphness) {
5876 lefthandmorphness = 0;
5877 lefthandmorphend = 1;
5878 targetlefthandmorphness = 1;
5881 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5884 targetheadmorphness = 1;
5891 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5892 (victim->aitype != searchtype) && (aitype != passivetype) &&
5893 (aitype != searchtype) && (victim->id < Person::players.size())) {
5894 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5898 if (!dead && animTarget != hurtidleanim) {
5899 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5900 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5903 targetheadmorphness = 1;
5908 if (weaponactive != -1) {
5909 if (weapons[weaponids[weaponactive]].getType() != staff) {
5910 righthandmorphstart = 1;
5911 righthandmorphend = 1;
5913 if (weapons[weaponids[weaponactive]].getType() == staff) {
5914 righthandmorphstart = 2;
5915 righthandmorphend = 2;
5917 targetrighthandmorphness = 1;
5920 terrainnormal = terrain.getNormal(coords.x, coords.z);
5922 if (Animation::animations[animTarget].attack != reversal) {
5923 if (!isnormal(coords.x)) {
5932 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5933 facing = flatfacing;
5934 ReflectVector(&facing, terrainnormal);
5938 animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5940 targettilt2 = -facing.y * 20;
5946 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim) {
5949 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5950 flatvelocity = velocity;
5952 flatvelspeed = findLength(&flatvelocity);
5953 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5954 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5955 if (velocity.y < 0) {
5958 if (velocity.y < 0) {
5961 if (targettilt > 25) {
5964 if (targettilt < -25) {
5969 if (targettilt2 > 45) {
5972 if (targettilt2 < -45) {
5975 if (abs(tilt2 - targettilt2) < multiplier * 400) {
5976 tilt2 = targettilt2;
5977 } else if (tilt2 > targettilt2) {
5978 tilt2 -= multiplier * 400;
5979 } else if (tilt2 < targettilt2) {
5980 tilt2 += multiplier * 400;
5982 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5991 if (!isnormal(targettilt) && targettilt) {
5994 if (!isnormal(targettilt2) && targettilt2) {
5999 if (animTarget == rabbittackleanim) {
6000 velocity += facing * multiplier * speed * 700 * scale;
6001 velspeed = findLength(&velocity);
6002 if (velspeed > speed * 65 * scale) {
6003 velocity /= velspeed;
6004 velspeed = speed * 65 * scale;
6005 velocity *= velspeed;
6007 velocity.y += gravity * multiplier * 20;
6008 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6009 velspeed = findLength(&velocity);
6010 velocity = flatfacing * velspeed;
6012 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
6013 if (isRun() || animTarget == rabbitkickanim) {
6014 velocity += facing * multiplier * speed * 700 * scale;
6015 velspeed = findLength(&velocity);
6016 if (velspeed > speed * 45 * scale) {
6017 velocity /= velspeed;
6018 velspeed = speed * 45 * scale;
6019 velocity *= velspeed;
6021 velocity.y += gravity * multiplier * 20;
6022 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6023 velspeed = findLength(&velocity);
6024 if (velspeed < speed * 30 * scale) {
6025 velspeed = speed * 30 * scale;
6027 velocity = flatfacing * velspeed;
6029 } else if (isRun()) {
6030 velocity += facing * multiplier * speed * 700 * scale;
6031 velspeed = findLength(&velocity);
6032 if (creature == rabbittype) {
6033 if (velspeed > speed * 55 * scale) {
6034 velocity /= velspeed;
6035 velspeed = speed * 55 * scale;
6036 velocity *= velspeed;
6039 if (creature == wolftype) {
6040 if (velspeed > speed * 75 * scale) {
6041 velocity /= velspeed;
6042 velspeed = speed * 75 * scale;
6043 velocity *= velspeed;
6046 velocity.y += gravity * multiplier * 20;
6047 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6048 velspeed = findLength(&velocity);
6049 velocity = flatfacing * velspeed;
6052 if (animTarget == rollanim && targetFrame().label != 6) {
6053 velocity += facing * multiplier * speed * 700 * scale;
6054 velspeed = findLength(&velocity);
6055 if (velspeed > speed * 45 * scale) {
6056 velocity /= velspeed;
6057 velspeed = speed * 45 * scale;
6058 velocity *= velspeed;
6060 velocity.y += gravity * multiplier * 20;
6061 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6062 velspeed = findLength(&velocity);
6063 velocity = flatfacing * velspeed;
6066 if (animTarget == sneakanim || animTarget == walkanim) {
6067 velocity += facing * multiplier * speed * 700 * scale;
6068 velspeed = findLength(&velocity);
6069 if (velspeed > speed * 12 * scale) {
6070 velocity /= velspeed;
6071 velspeed = speed * 12 * scale;
6072 velocity *= velspeed;
6074 velocity.y += gravity * multiplier * 20;
6075 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6076 velspeed = findLength(&velocity);
6077 velocity = flatfacing * velspeed;
6080 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
6081 velocity += facing * multiplier * speed * 700 * scale;
6082 velspeed = findLength(&velocity);
6083 if (velspeed > speed * 2 * scale) {
6084 velocity /= velspeed;
6085 velspeed = speed * 2 * scale;
6086 velocity *= velspeed;
6088 velocity.y += gravity * multiplier * 20;
6089 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6090 velspeed = findLength(&velocity);
6091 velocity = flatfacing * velspeed;
6094 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
6095 velocity -= facing * multiplier * speed * 700 * scale;
6096 velspeed = findLength(&velocity);
6097 if (velspeed > speed * 2 * scale) {
6098 velocity /= velspeed;
6099 velspeed = speed * 2 * scale;
6100 velocity *= velspeed;
6102 velocity.y += gravity * multiplier * 20;
6103 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6104 velspeed = findLength(&velocity);
6105 velocity = flatfacing * velspeed * -1;
6108 if (animTarget == fightsidestep) {
6109 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
6110 velspeed = findLength(&velocity);
6111 if (velspeed > speed * 12 * scale) {
6112 velocity /= velspeed;
6113 velspeed = speed * 12 * scale;
6114 velocity *= velspeed;
6116 velocity.y += gravity * multiplier * 20;
6117 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6118 velspeed = findLength(&velocity);
6119 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
6122 if (animTarget == staggerbackhighanim) {
6123 coords -= facing * multiplier * speed * 16 * scale;
6126 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
6127 coords -= facing * multiplier * speed * 20 * scale;
6131 if (animTarget == backhandspringanim) {
6132 //coords-=facing*multiplier*50*scale;
6133 velocity += facing * multiplier * speed * 700 * scale * -1;
6134 velspeed = findLength(&velocity);
6135 if (velspeed > speed * 50 * scale) {
6136 velocity /= velspeed;
6137 velspeed = speed * 50 * scale;
6138 velocity *= velspeed;
6140 velocity.y += gravity * multiplier * 20;
6141 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6142 velspeed = findLength(&velocity);
6143 velocity = flatfacing * velspeed * -1;
6145 if (animTarget == dodgebackanim) {
6146 //coords-=facing*multiplier*50*scale;
6147 velocity += facing * multiplier * speed * 700 * scale * -1;
6148 velspeed = findLength(&velocity);
6149 if (velspeed > speed * 60 * scale) {
6150 velocity /= velspeed;
6151 velspeed = speed * 60 * scale;
6152 velocity *= velspeed;
6154 velocity.y += gravity * multiplier * 20;
6155 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6156 velspeed = findLength(&velocity);
6157 velocity = flatfacing * velspeed * -1;
6160 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6161 velspeed = findLength(&velocity);
6164 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6165 velocity.y += gravity * multiplier;
6168 if (animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6169 coords += velocity * multiplier;
6172 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6173 if (isFlip() && targetFrame().label == 7) {
6177 if (animTarget == jumpupanim) {
6179 animTarget = getIdle();
6186 pause_sound(whooshsound);
6187 OPENAL_SetVolume(channels[whooshsound], 0);
6190 if (animTarget == jumpdownanim || isFlip()) {
6194 animTarget = getLanding();
6195 emit_sound_at(landsound, coords, 128.);
6198 addEnvSound(coords);
6203 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6204 coords.y += gravity * multiplier * 2;
6206 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
6207 coords.y = terrain.getHeight(coords.x, coords.z);
6211 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)) {
6212 velspeed = findLength(&velocity);
6214 if (velspeed < multiplier * 300 * scale) {
6217 velocity -= velocity / velspeed * multiplier * 300 * scale;
6219 if (velspeed > 5 && (isLanding() || isLandhard())) {
6220 skiddingdelay += multiplier;
6221 if (skiddelay <= 0) {
6222 FootLand(leftfoot, .5);
6223 FootLand(rightfoot, .5);
6232 velspeed = findLength(&velocity);
6234 if (velspeed > 5 && (isLanding() || isLandhard())) {
6235 skiddingdelay += multiplier;
6236 if (skiddelay <= 0) {
6237 FootLand(leftfoot, .5);
6238 FootLand(rightfoot, .5);
6246 if (skiddingdelay < 0) {
6247 skiddingdelay += multiplier;
6249 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
6251 if (!onterrain || environment == grassyenvironment) {
6252 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
6254 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
6258 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
6259 terrainnormal = victim->coords - coords;
6260 Normalise(&terrainnormal);
6261 targetyaw = -asin(0 - terrainnormal.x);
6262 targetyaw *= 360 / 6.28;
6263 if (terrainnormal.z < 0) {
6264 targetyaw = 180 - targetyaw;
6266 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
6269 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
6270 targetyaw = victim->targetyaw;
6272 if (animTarget == rabbittacklinganim) {
6273 coords = victim->coords;
6276 skeleton.oldfree = skeleton.free;
6280 midterrain.x = terrain.size * terrain.scale / 2;
6281 midterrain.z = terrain.size * terrain.scale / 2;
6282 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
6284 tempposit = coords - midterrain;
6286 Normalise(&tempposit);
6287 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
6288 coords.x = tempposit.x + midterrain.x;
6289 coords.z = tempposit.z + midterrain.z;
6294 * inverse kinematics helper function
6296 void IKHelper(Person* p, float interp)
6298 XYZ point, change, change2;
6299 float heightleft, heightright;
6301 // TODO: implement localToWorld and worldToLocal
6302 // but keep in mind it won't be the same math if player is ragdolled or something
6303 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
6304 // then comb through code for places where to use it
6306 // point = localToWorld(jointPos(leftfoot))
6307 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
6308 // adjust height of foot
6309 heightleft = terrain.getHeight(point.x, point.z) + .04;
6310 point.y = heightleft;
6311 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
6312 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
6313 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
6314 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
6315 // move ankle along with foot
6316 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
6317 // average knee pos between old and new pos
6318 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
6320 // do same as above for right leg
6321 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
6322 heightright = terrain.getHeight(point.x, point.z) + .04;
6323 point.y = heightright;
6324 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
6325 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
6326 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
6327 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
6328 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
6330 // fix up skeleton now that we've moved body parts?
6331 p->skeleton.DoConstraints(&p->coords, &p->scale);
6338 int Person::DrawSkeleton()
6340 int oldplayerdetail;
6341 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6342 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6352 glAlphaFunc(GL_GREATER, 0.0001);
6354 float terrainheight;
6356 if (!isnormal(yaw)) {
6359 if (!isnormal(tilt)) {
6362 if (!isnormal(tilt2)) {
6365 oldplayerdetail = playerdetail;
6367 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6370 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6373 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6379 if (playerdetail != oldplayerdetail) {
6381 normalsupdatedelay = 0;
6383 static float updatedelaychange;
6384 static float morphness;
6385 static float framemult;
6387 skeleton.FindForwards();
6388 if (howactive == typesittingwall) {
6389 skeleton.specialforward[1] = 0;
6390 skeleton.specialforward[1].z = 1;
6396 static int weaponattachmuscle;
6397 static int weaponrotatemuscle;
6398 static XYZ weaponpoint;
6399 static int start, endthing;
6400 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6401 if (!isSleeping() && !isSitting()) {
6402 // TODO: give these meaningful names
6403 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6404 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard() || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6406 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6408 if (creature == wolftype) {
6413 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6414 IKHelper(this, target);
6415 if (creature == wolftype) {
6416 IKHelper(this, target);
6420 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6421 IKHelper(this, 1 - target);
6422 if (creature == wolftype) {
6423 IKHelper(this, 1 - target);
6428 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())) {
6431 targetheadyaw = -targetyaw;
6432 targetheadpitch = 0;
6433 if (Animation::animations[animTarget].attack == 3) {
6434 targetheadyaw += 180;
6437 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6438 skeleton.drawmodel.vertex[i] = 0;
6439 skeleton.drawmodel.vertex[i].y = 999;
6441 for (int i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6442 skeleton.drawmodellow.vertex[i] = 0;
6443 skeleton.drawmodellow.vertex[i].y = 999;
6445 for (int i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6446 skeleton.drawmodelclothes.vertex[i] = 0;
6447 skeleton.drawmodelclothes.vertex[i].y = 999;
6449 for (unsigned int i = 0; i < skeleton.muscles.size(); i++) {
6450 // convenience renames
6451 const int p1 = skeleton.muscles[i].parent1->label;
6452 const int p2 = skeleton.muscles[i].parent2->label;
6454 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6459 if (p1 == righthand || p2 == righthand) {
6460 morphness = righthandmorphness;
6461 start = righthandmorphstart;
6462 endthing = righthandmorphend;
6464 if (p1 == lefthand || p2 == lefthand) {
6465 morphness = lefthandmorphness;
6466 start = lefthandmorphstart;
6467 endthing = lefthandmorphend;
6469 if (p1 == head || p2 == head) {
6470 morphness = headmorphness;
6471 start = headmorphstart;
6472 endthing = headmorphend;
6474 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6475 morphness = chestmorphness;
6476 start = chestmorphstart;
6477 endthing = chestmorphend;
6479 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6480 morphness = tailmorphness;
6481 start = tailmorphstart;
6482 endthing = tailmorphend;
6485 skeleton.FindRotationMuscle(i, animTarget);
6487 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6488 glMatrixMode(GL_MODELVIEW);
6491 if (!skeleton.free) {
6492 glRotatef(tilt2, 1, 0, 0);
6494 if (!skeleton.free) {
6495 glRotatef(tilt, 0, 0, 1);
6498 glTranslatef(mid.x, mid.y, mid.z);
6500 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6501 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6503 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6504 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6506 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6507 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6509 if (playerdetail || skeleton.free == 3) {
6510 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6511 XYZ& v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6512 XYZ& v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6513 glMatrixMode(GL_MODELVIEW);
6515 if (p1 == abdomen || p2 == abdomen) {
6516 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(1).x,
6517 (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(1).y,
6518 (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(1).z);
6520 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6521 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(2).x,
6522 (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(2).y,
6523 (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(2).z);
6525 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6526 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(3).x,
6527 (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(3).y,
6528 (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(3).z);
6530 if (p1 == head || p2 == head) {
6531 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(0).x,
6532 (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(0).y,
6533 (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(0).z);
6535 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6536 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6537 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6538 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6542 if (!playerdetail || skeleton.free == 3) {
6543 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6544 XYZ& v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6545 glMatrixMode(GL_MODELVIEW);
6547 if (p1 == abdomen || p2 == abdomen) {
6548 glTranslatef(v0.x * getProportionXYZ(1).x,
6549 v0.y * getProportionXYZ(1).y,
6550 v0.z * getProportionXYZ(1).z);
6552 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6553 glTranslatef(v0.x * getProportionXYZ(2).x,
6554 v0.y * getProportionXYZ(2).y,
6555 v0.z * getProportionXYZ(2).z);
6557 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6558 glTranslatef(v0.x * getProportionXYZ(3).x,
6559 v0.y * getProportionXYZ(3).y,
6560 v0.z * getProportionXYZ(3).z);
6562 if (p1 == head || p2 == head) {
6563 glTranslatef(v0.x * getProportionXYZ(0).x,
6564 v0.y * getProportionXYZ(0).y,
6565 v0.z * getProportionXYZ(0).z);
6568 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6569 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6570 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6571 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6577 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6578 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6580 glMatrixMode(GL_MODELVIEW);
6583 if (!skeleton.free) {
6584 glRotatef(tilt2, 1, 0, 0);
6586 if (!skeleton.free) {
6587 glRotatef(tilt, 0, 0, 1);
6589 glTranslatef(mid.x, mid.y, mid.z);
6590 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6591 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6593 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6594 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6596 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6597 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6599 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6600 XYZ& v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6601 glMatrixMode(GL_MODELVIEW);
6603 if (p1 == abdomen || p2 == abdomen) {
6604 glTranslatef(v0.x * getProportionXYZ(1).x,
6605 v0.y * getProportionXYZ(1).y,
6606 v0.z * getProportionXYZ(1).z);
6608 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6609 glTranslatef(v0.x * getProportionXYZ(2).x,
6610 v0.y * getProportionXYZ(2).y,
6611 v0.z * getProportionXYZ(2).z);
6613 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6614 glTranslatef(v0.x * getProportionXYZ(3).x,
6615 v0.y * getProportionXYZ(3).y,
6616 v0.z * getProportionXYZ(3).z);
6618 if (p1 == head || p2 == head) {
6619 glTranslatef(v0.x * getProportionXYZ(0).x,
6620 v0.y * getProportionXYZ(0).y,
6621 v0.z * getProportionXYZ(0).z);
6623 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6624 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6625 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6626 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6631 updatedelay = 1 + (float)(Random() % 100) / 1000;
6633 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6634 normalsupdatedelay = 1;
6635 if (playerdetail || skeleton.free == 3) {
6636 skeleton.drawmodel.CalculateNormals(0);
6638 if (!playerdetail || skeleton.free == 3) {
6639 skeleton.drawmodellow.CalculateNormals(0);
6641 if (skeleton.clothes) {
6642 skeleton.drawmodelclothes.CalculateNormals(0);
6645 if (playerdetail || skeleton.free == 3) {
6646 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6648 if (!playerdetail || skeleton.free == 3) {
6649 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6651 if (skeleton.clothes) {
6652 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6657 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6658 if (updatedelaychange > -realmultiplier * 30) {
6659 updatedelaychange = -realmultiplier * 30;
6661 if (updatedelaychange > -framemult * 4) {
6662 updatedelaychange = -framemult * 4;
6664 if (skeleton.free == 1) {
6665 updatedelaychange *= 6;
6668 updatedelaychange *= 8;
6670 updatedelay += updatedelaychange;
6672 glMatrixMode(GL_MODELVIEW);
6674 glTranslatef(coords.x, coords.y - .02, coords.z);
6675 if (!skeleton.free) {
6676 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6677 glRotatef(yaw, 0, 1, 0);
6681 glColor4f(.4, 1, .4, 1);
6682 glDisable(GL_LIGHTING);
6683 glDisable(GL_TEXTURE_2D);
6686 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6687 XYZ& v0 = skeleton.drawmodel.vertex[i];
6688 glVertex3f(v0.x, v0.y, v0.z);
6695 for (unsigned int i = 0; i < skeleton.drawmodel.Triangles.size(); i++) {
6696 const XYZ& v0 = skeleton.drawmodel.getTriangleVertex(i, 0);
6697 const XYZ& v1 = skeleton.drawmodel.getTriangleVertex(i, 1);
6698 const XYZ& v2 = skeleton.drawmodel.getTriangleVertex(i, 2);
6699 glVertex3f(v0.x, v0.y, v0.z);
6700 glVertex3f(v1.x, v1.y, v1.z);
6701 glVertex3f(v1.x, v1.y, v1.z);
6702 glVertex3f(v2.x, v2.y, v2.z);
6703 glVertex3f(v2.x, v2.y, v2.z);
6704 glVertex3f(v0.x, v0.y, v0.z);
6711 terrainlight = terrain.getLighting(coords.x, coords.z);
6712 distance = distsq(&viewer, &coords);
6713 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6718 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6719 if (terrainheight < 1) {
6722 if (terrainheight > 1.7) {
6723 terrainheight = 1.7;
6726 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6727 glDisable(GL_BLEND);
6728 glAlphaFunc(GL_GREATER, 0.0001);
6729 glEnable(GL_TEXTURE_2D);
6731 glDisable(GL_TEXTURE_2D);
6732 glColor4f(.7, .35, 0, .5);
6734 glEnable(GL_LIGHTING);
6737 if (Tutorial::active && id != 0) {
6738 glColor4f(.7, .7, .7, 0.6);
6740 glEnable(GL_LIGHTING);
6742 if (canattack && cananger) {
6743 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6744 glDisable(GL_TEXTURE_2D);
6745 glColor4f(1, 0, 0, 0.8);
6748 glMatrixMode(GL_TEXTURE);
6750 glTranslatef(0, -smoketex, 0);
6751 glTranslatef(-smoketex, 0, 0);
6755 if (Tutorial::active && (id != 0)) {
6756 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6758 skeleton.drawmodel.draw();
6762 if (!playerdetail) {
6763 if (Tutorial::active && (id != 0)) {
6764 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6766 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6770 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed)) {
6771 if (Tutorial::active && id != 0) {
6773 glMatrixMode(GL_MODELVIEW);
6774 glEnable(GL_TEXTURE_2D);
6775 glColor4f(.7, .7, .7, 0.6);
6777 glEnable(GL_LIGHTING);
6779 if (canattack && cananger) {
6780 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6781 glDisable(GL_TEXTURE_2D);
6782 glColor4f(1, 0, 0, 0.8);
6785 glMatrixMode(GL_TEXTURE);
6787 glTranslatef(0, -smoketex * .6, 0);
6788 glTranslatef(smoketex * .6, 0, 0);
6791 if (Tutorial::active && (id != 0)) {
6792 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6794 skeleton.drawmodel.draw();
6798 if (!playerdetail) {
6799 if (Tutorial::active && (id != 0)) {
6800 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6802 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6808 if (Tutorial::active && id != 0) {
6810 glMatrixMode(GL_MODELVIEW);
6811 glEnable(GL_TEXTURE_2D);
6813 if (skeleton.clothes) {
6817 skeleton.drawmodelclothes.draw();
6820 skeleton.drawmodelclothes.drawimmediate();
6827 if (num_weapons > 0) {
6828 for (k = 0; k < num_weapons; k++) {
6829 int i = weaponids[k];
6830 if (weaponactive == k) {
6831 if (weapons[i].getType() != staff) {
6832 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6833 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6834 weaponattachmuscle = j;
6837 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6838 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) {
6839 weaponrotatemuscle = j;
6842 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6843 if (creature == wolftype) {
6844 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6847 if (weapons[i].getType() == staff) {
6848 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6849 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6850 weaponattachmuscle = j;
6853 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6854 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) {
6855 weaponrotatemuscle = j;
6858 //weaponpoint=jointPos(rightwrist);
6859 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6860 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6861 XYZ tempnormthing, vec1, vec2;
6862 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6863 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6864 CrossProduct(&vec1, &vec2, &tempnormthing);
6865 Normalise(&tempnormthing);
6866 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim) {
6867 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6871 if (weaponactive != k && weaponstuck != k) {
6872 if (weapons[i].getType() == knife) {
6873 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6875 if (weapons[i].getType() == sword) {
6876 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6878 if (weapons[i].getType() == staff) {
6879 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6881 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6882 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) {
6883 weaponrotatemuscle = j;
6887 if (weaponstuck == k) {
6888 if (weaponstuckwhere == 0) {
6889 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6891 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6893 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6894 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) {
6895 weaponrotatemuscle = j;
6899 if (skeleton.free) {
6900 weapons[i].position = weaponpoint * scale + coords;
6901 weapons[i].bigrotation = 0;
6902 weapons[i].bigtilt = 0;
6903 weapons[i].bigtilt2 = 0;
6905 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;
6906 weapons[i].bigrotation = yaw;
6907 weapons[i].bigtilt = tilt;
6908 weapons[i].bigtilt2 = tilt2;
6910 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6911 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6912 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6913 if (weaponactive == k) {
6914 if (weapons[i].getType() == knife) {
6915 weapons[i].smallrotation = 180;
6916 weapons[i].smallrotation2 = 0;
6917 if (isCrouch() || wasCrouch()) {
6918 weapons[i].smallrotation2 = 20;
6920 if (animTarget == hurtidleanim) {
6921 weapons[i].smallrotation2 = 50;
6923 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6924 XYZ temppoint1, temppoint2;
6927 temppoint1 = jointPos(righthand);
6928 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6929 distance = findDistance(&temppoint1, &temppoint2);
6930 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6931 weapons[i].rotation2 *= 360 / 6.28;
6934 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6935 weapons[i].rotation1 *= 360 / 6.28;
6936 weapons[i].rotation3 = 0;
6937 weapons[i].smallrotation = -90;
6938 weapons[i].smallrotation2 = 0;
6939 if (temppoint1.x > temppoint2.x) {
6940 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6943 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6944 XYZ temppoint1, temppoint2;
6947 temppoint1 = jointPos(righthand);
6948 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6949 distance = findDistance(&temppoint1, &temppoint2);
6950 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6951 weapons[i].rotation2 *= 360 / 6.28;
6954 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6955 weapons[i].rotation1 *= 360 / 6.28;
6956 weapons[i].rotation3 = 0;
6957 weapons[i].smallrotation = 90;
6958 weapons[i].smallrotation2 = 0;
6959 if (temppoint1.x > temppoint2.x) {
6960 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6963 if (animTarget == knifethrowanim) {
6964 weapons[i].smallrotation = 90;
6965 //weapons[i].smallrotation2=-90;
6966 weapons[i].smallrotation2 = 0;
6967 weapons[i].rotation1 = 0;
6968 weapons[i].rotation2 = 0;
6969 weapons[i].rotation3 = 0;
6971 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6972 weapons[i].smallrotation = -90;
6973 weapons[i].rotation1 = 0;
6974 weapons[i].rotation2 = 0;
6975 weapons[i].rotation3 = 0;
6978 if (weapons[i].getType() == sword) {
6979 weapons[i].smallrotation = 0;
6980 weapons[i].smallrotation2 = 0;
6981 if (animTarget == knifethrowanim) {
6982 weapons[i].smallrotation = -90;
6983 weapons[i].smallrotation2 = 0;
6984 weapons[i].rotation1 = 0;
6985 weapons[i].rotation2 = 0;
6986 weapons[i].rotation3 = 0;
6988 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)) {
6989 XYZ temppoint1, temppoint2;
6992 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6993 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6994 distance = findDistance(&temppoint1, &temppoint2);
6995 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6996 weapons[i].rotation2 *= 360 / 6.28;
6999 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7000 weapons[i].rotation1 *= 360 / 6.28;
7001 weapons[i].rotation3 = 0;
7002 weapons[i].smallrotation = 90;
7003 weapons[i].smallrotation2 = 0;
7004 if (temppoint1.x > temppoint2.x) {
7005 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7009 if (weapons[i].getType() == staff) {
7010 weapons[i].smallrotation = 100;
7011 weapons[i].smallrotation2 = 0;
7012 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
7013 XYZ temppoint1, temppoint2;
7016 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
7017 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7018 distance = findDistance(&temppoint1, &temppoint2);
7019 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7020 weapons[i].rotation2 *= 360 / 6.28;
7023 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7024 weapons[i].rotation1 *= 360 / 6.28;
7025 weapons[i].rotation3 = 0;
7026 weapons[i].smallrotation = 90;
7027 weapons[i].smallrotation2 = 0;
7028 if (temppoint1.x > temppoint2.x) {
7029 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7034 if (weaponactive != k && weaponstuck != k) {
7035 if (weapons[i].getType() == knife) {
7036 weapons[i].smallrotation = -70;
7037 weapons[i].smallrotation2 = 10;
7039 if (weapons[i].getType() == sword) {
7040 weapons[i].smallrotation = -100;
7041 weapons[i].smallrotation2 = -8;
7043 if (weapons[i].getType() == staff) {
7044 weapons[i].smallrotation = -100;
7045 weapons[i].smallrotation2 = -8;
7048 if (weaponstuck == k) {
7049 if (weaponstuckwhere == 0) {
7050 weapons[i].smallrotation = 180;
7052 weapons[i].smallrotation = 0;
7054 weapons[i].smallrotation2 = 10;
7061 if (skeleton.free) {
7064 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump()) {
7067 if (animCurrent != animTarget) {
7070 if (skeleton.free == 2) {
7079 int Person::SphereCheck(XYZ* p1, float radius, XYZ* p, XYZ* move, float* rotate, Model* model)
7081 static float distance;
7082 static float olddistance;
7083 static int intersecting;
7084 static int firstintersecting;
7087 static XYZ start, end;
7088 static float slopethreshold = -.4;
7090 firstintersecting = -1;
7094 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius) {
7098 *p1 = DoRotation(*p1, 0, -*rotate, 0);
7100 for (int i = 0; i < 4; i++) {
7101 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7102 if (model->Triangles[j].facenormal.y <= slopethreshold) {
7104 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)));
7105 if (distance < radius) {
7106 point = *p1 - model->Triangles[j].facenormal * distance;
7107 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]])) {
7110 if (!intersecting) {
7111 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7112 &model->vertex[model->Triangles[j].vertex[1]],
7115 if (!intersecting) {
7116 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
7117 &model->vertex[model->Triangles[j].vertex[2]],
7120 if (!intersecting) {
7121 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7122 &model->vertex[model->Triangles[j].vertex[2]],
7126 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7130 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)) {
7131 p1->y = point.y + radius;
7132 if ((animTarget == jumpdownanim || isFlip())) {
7133 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4)) {
7137 if (animTarget == jumpupanim) {
7139 animTarget = getIdle();
7146 pause_sound(whooshsound);
7147 OPENAL_SetVolume(channels[whooshsound], 0);
7150 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
7154 animTarget = getLanding();
7155 emit_sound_at(landsound, coords, 128.);
7158 addEnvSound(coords);
7165 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7166 olddistance = distance;
7167 firstintersecting = j;
7172 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7173 if (model->Triangles[j].facenormal.y > slopethreshold) {
7176 start.y -= radius / 4;
7177 XYZ& v0 = model->vertex[model->Triangles[j].vertex[0]];
7178 XYZ& v1 = model->vertex[model->Triangles[j].vertex[1]];
7179 XYZ& v2 = model->vertex[model->Triangles[j].vertex[2]];
7180 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)));
7181 if (distance < radius * .5) {
7182 point = start - model->Triangles[j].facenormal * distance;
7183 if (PointInTriangle(&point, model->Triangles[j].facenormal, &v0, &v1, &v2)) {
7186 if (!intersecting) {
7187 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
7189 if (!intersecting) {
7190 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7192 if (!intersecting) {
7193 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7196 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7197 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
7199 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;
7200 if (findLengthfast(&start) < findLengthfast(&velocity)) {
7204 *p1 += model->Triangles[j].facenormal * (distance - radius * .5);
7207 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7208 olddistance = distance;
7209 firstintersecting = j;
7216 *p = DoRotation(*p, 0, *rotate, 0);
7220 *p1 = DoRotation(*p1, 0, *rotate, 0);
7223 return firstintersecting;
7226 int findPathDist(int start, int end)
7231 unsigned int smallestcount = 1000;
7232 for (char i = 0; i < 50; i++) {
7233 unsigned int count = 0;
7238 while (last != end && count < 30) {
7240 for (int j = 0; j < Game::numpathpoints; j++) {
7241 if (j != last && j != last2 && j != last3 && j != last4) {
7243 if (Game::numpathpointconnect[j]) {
7244 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7245 if (Game::pathpointconnect[j][k] == last) {
7251 if (Game::numpathpointconnect[last]) {
7252 for (int k = 0; k < Game::numpathpointconnect[last]; k++) {
7253 if (Game::pathpointconnect[last][k] == j) {
7260 if (closest == -1 || Random() % 2 == 0) {
7272 if (count < smallestcount) {
7273 smallestcount = count;
7276 return smallestcount;
7279 void Person::takeWeapon(int weaponId)
7282 weapons[weaponId].owner = id;
7283 if (num_weapons > 0) {
7284 weaponids[num_weapons] = weaponids[0];
7287 weaponids[0] = weaponId;
7290 void Person::addClothes()
7292 if (numclothes > 0) {
7293 for (int i = 0; i < numclothes; i++) {
7300 bool Person::addClothes(const int& clothesId)
7303 const std::string fileName = clothes[clothesId];
7305 GLubyte* array = &skeleton.skinText[0];
7309 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
7314 float tintr = clothestintr[clothesId];
7315 float tintg = clothestintg[clothesId];
7316 float tintb = clothestintb[clothesId];
7338 int bytesPerPixel = texture.bpp / 8;
7342 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
7343 if (bytesPerPixel == 3) {
7345 } else if ((i + 1) % 4 == 0) {
7346 alphanum = texture.data[i];
7348 if ((i + 1) % 4 || bytesPerPixel == 3) {
7350 texture.data[i] *= tintr;
7353 texture.data[i] *= tintg;
7356 texture.data[i] *= tintb;
7358 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
7370 if (aitype != playercontrolled && !Dialog::inDialog()) {
7372 //disable movement in editor
7373 if (Game::editorenabled) {
7378 if (distsqflat(&Person::players[0]->coords, &coords) < 30 &&
7379 Person::players[0]->coords.y > coords.y + 2 &&
7380 !Person::players[0]->onterrain) {
7385 if (aitype == pathfindtype) {
7386 if (finalpathfindpoint == -1) {
7387 float closestdistance;
7388 float tempdist = 0.0f;
7392 closestdistance = -1;
7393 for (int j = 0; j < Game::numpathpoints; j++) {
7394 if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) {
7395 closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]);
7397 finaltarget = Game::pathpoint[j];
7400 finalpathfindpoint = closest;
7401 for (int j = 0; j < Game::numpathpoints; j++) {
7402 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7403 DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7404 if (sq(tempdist) < closestdistance) {
7405 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7406 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7407 closestdistance = sq(tempdist);
7409 finaltarget = colpoint;
7414 finalpathfindpoint = closest;
7416 if (targetpathfindpoint == -1) {
7417 float closestdistance;
7418 float tempdist = 0.0f;
7422 closestdistance = -1;
7423 if (lastpathfindpoint == -1) {
7424 for (int j = 0; j < Game::numpathpoints; j++) {
7425 if (j != lastpathfindpoint) {
7426 if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) {
7427 closestdistance = distsq(&coords, &Game::pathpoint[j]);
7432 targetpathfindpoint = closest;
7433 for (int j = 0; j < Game::numpathpoints; j++) {
7434 if (j != lastpathfindpoint) {
7435 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7436 DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7437 if (sq(tempdist) < closestdistance) {
7438 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7439 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7440 closestdistance = sq(tempdist);
7447 targetpathfindpoint = closest;
7449 for (int j = 0; j < Game::numpathpoints; j++) {
7450 if (j != lastpathfindpoint &&
7451 j != lastpathfindpoint2 &&
7452 j != lastpathfindpoint3 &&
7453 j != lastpathfindpoint4) {
7455 if (Game::numpathpointconnect[j]) {
7456 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7457 if (Game::pathpointconnect[j][k] == lastpathfindpoint) {
7463 if (Game::numpathpointconnect[lastpathfindpoint]) {
7464 for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++) {
7465 if (Game::pathpointconnect[lastpathfindpoint][k] == j) {
7472 tempdist = findPathDist(j, finalpathfindpoint);
7473 if (closest == -1 || tempdist < closestdistance) {
7474 closestdistance = tempdist;
7480 targetpathfindpoint = closest;
7483 losupdatedelay -= multiplier;
7485 targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]);
7486 lookyaw = targetyaw;
7488 //reached target point
7489 if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) {
7490 lastpathfindpoint4 = lastpathfindpoint3;
7491 lastpathfindpoint3 = lastpathfindpoint2;
7492 lastpathfindpoint2 = lastpathfindpoint;
7493 lastpathfindpoint = targetpathfindpoint;
7494 if (lastpathfindpoint2 == -1) {
7495 lastpathfindpoint2 = lastpathfindpoint;
7497 if (lastpathfindpoint3 == -1) {
7498 lastpathfindpoint3 = lastpathfindpoint2;
7500 if (lastpathfindpoint4 == -1) {
7501 lastpathfindpoint4 = lastpathfindpoint3;
7503 targetpathfindpoint = -1;
7505 if (distsqflat(&coords, &finalfinaltarget) <
7506 distsqflat(&coords, &finaltarget) ||
7507 distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) ||
7508 lastpathfindpoint == finalpathfindpoint) {
7509 aitype = passivetype;
7520 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7521 targetyaw += 90 * (whichdirection * 2 - 1);
7524 if (collided < 1 || animTarget != jumpupanim) {
7527 if ((collided > .8 && jumppower >= 5)) {
7531 if ((!Tutorial::active || cananger) &&
7533 !Person::players[0]->dead &&
7534 distsq(&coords, &Person::players[0]->coords) < 400 &&
7536 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7537 Animation::animations[Person::players[0]->animTarget].height != lowheight &&
7538 !Game::editorenabled &&
7539 (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain)) {
7540 aitype = attacktypecutoff;
7542 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7543 Animation::animations[Person::players[0]->animTarget].height == highheight &&
7544 !Game::editorenabled) {
7545 aitype = attacktypecutoff;
7548 if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7549 losupdatedelay = .2;
7550 for (unsigned j = 0; j < Person::players.size(); j++) {
7551 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7552 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7553 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7554 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7555 if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain) {
7556 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) ||
7557 (Person::players[j]->animTarget == hanganim &&
7558 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7559 aitype = searchtype;
7561 lastseen = Person::players[j]->coords;
7572 if (aitype == attacktypecutoff && Game::musictype != 2) {
7573 if (creature != wolftype) {
7580 if (aitype != passivetype && Game::leveltime > .5) {
7581 howactive = typeactive;
7584 if (aitype == passivetype) {
7585 aiupdatedelay -= multiplier;
7586 losupdatedelay -= multiplier;
7587 lastseentime += multiplier;
7588 pausetime -= multiplier;
7589 if (lastseentime > 1) {
7593 if (aiupdatedelay < 0) {
7594 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7595 targetyaw = roughDirectionTo(coords, waypoints[waypoint]);
7596 lookyaw = targetyaw;
7597 aiupdatedelay = .05;
7599 if (distsqflat(&coords, &waypoints[waypoint]) < 1) {
7600 if (waypointtype[waypoint] == wppause) {
7604 if (waypoint > numwaypoints - 1) {
7610 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7622 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7623 if (!avoidsomething) {
7624 targetyaw += 90 * (whichdirection * 2 - 1);
7626 XYZ leftpos, rightpos;
7627 float leftdist, rightdist;
7628 leftpos = coords + DoRotation(facing, 0, 90, 0);
7629 rightpos = coords - DoRotation(facing, 0, 90, 0);
7630 leftdist = distsq(&leftpos, &avoidwhere);
7631 rightdist = distsq(&rightpos, &avoidwhere);
7632 if (leftdist < rightdist) {
7640 if (collided < 1 || animTarget != jumpupanim) {
7643 if ((collided > .8 && jumppower >= 5)) {
7648 if (!Game::editorenabled) {
7649 if (howactive <= typesleeping) {
7650 if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile) {
7651 for (int j = 0; j < numenvsounds; j++) {
7652 float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
7653 if (vol > 0 && distsq(&coords, &envsound[j]) < 2 * (vol + vol * (creature == rabbittype) * 3)) {
7654 aitype = attacktypecutoff;
7660 if (aitype != passivetype) {
7661 if (howactive == typesleeping) {
7662 setTargetAnimation(getupfromfrontanim);
7664 howactive = typeactive;
7668 if (howactive < typesleeping &&
7669 ((!Tutorial::active || cananger) && hostile) &&
7670 !Person::players[0]->dead &&
7671 distsq(&coords, &Person::players[0]->coords) < 400 &&
7673 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7674 Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled) {
7675 aitype = attacktypecutoff;
7677 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7678 Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled) {
7679 aitype = attacktypecutoff;
7683 if (creature == wolftype) {
7685 for (unsigned j = 0; j < Person::players.size(); j++) {
7686 if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
7687 float smelldistance = 50;
7688 if (j == 0 && Person::players[j]->num_weapons > 0) {
7689 if (weapons[Person::players[j]->weaponids[0]].bloody) {
7690 smelldistance = 100;
7692 if (Person::players[j]->num_weapons == 2) {
7693 if (weapons[Person::players[j]->weaponids[1]].bloody) {
7694 smelldistance = 100;
7699 smelldistance = 100;
7701 windsmell = windvector;
7702 Normalise(&windsmell);
7703 windsmell = windsmell * 2 + Person::players[j]->coords;
7704 if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled) {
7705 aitype = attacktypecutoff;
7711 if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7712 losupdatedelay = .2;
7713 for (unsigned j = 0; j < Person::players.size(); j++) {
7714 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7715 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7716 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7717 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7718 if ((-1 == Object::checkcollide(
7719 DoRotation(jointPos(head), 0, yaw, 0) *
7722 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0) *
7723 Person::players[j]->scale +
7724 Person::players[j]->coords) &&
7725 !Person::players[j]->isWallJump()) ||
7726 (Person::players[j]->animTarget == hanganim &&
7727 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7729 if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight) {
7738 if (lastseentime <= 0) {
7739 aitype = searchtype;
7741 lastseen = Person::players[j]->coords;
7749 if (aitype == attacktypecutoff && Game::musictype != 2) {
7750 if (creature != wolftype) {
7754 if (creature == wolftype) {
7764 if (aitype == searchtype) {
7765 aiupdatedelay -= multiplier;
7766 losupdatedelay -= multiplier;
7768 lastseentime -= multiplier;
7770 lastchecktime -= multiplier;
7772 if (isRun() && !onground) {
7773 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7774 XYZ test2 = coords + facing;
7776 XYZ test = coords + facing;
7778 j = Object::checkcollide(test2, test, laststanding);
7780 j = Object::checkcollide(test2, test);
7784 setTargetAnimation(getStop());
7787 //aitype=passivetype;
7788 aitype = pathfindtype;
7789 finalfinaltarget = waypoints[waypoint];
7790 finalpathfindpoint = -1;
7791 targetpathfindpoint = -1;
7792 lastpathfindpoint = -1;
7793 lastpathfindpoint2 = -1;
7794 lastpathfindpoint3 = -1;
7795 lastpathfindpoint4 = -1;
7801 //check out last seen location
7802 if (aiupdatedelay < 0) {
7803 targetyaw = roughDirectionTo(coords, lastseen);
7804 lookyaw = targetyaw;
7805 aiupdatedelay = .05;
7808 if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) {
7811 lastseen.x += (float(Random() % 100) - 50) / 25;
7812 lastseen.z += (float(Random() % 100) - 50) / 25;
7823 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7824 if (!avoidsomething) {
7825 targetyaw += 90 * (whichdirection * 2 - 1);
7827 XYZ leftpos, rightpos;
7828 float leftdist, rightdist;
7829 leftpos = coords + DoRotation(facing, 0, 90, 0);
7830 rightpos = coords - DoRotation(facing, 0, 90, 0);
7831 leftdist = distsq(&leftpos, &avoidwhere);
7832 rightdist = distsq(&rightpos, &avoidwhere);
7833 if (leftdist < rightdist) {
7841 if (collided < 1 || animTarget != jumpupanim) {
7844 if ((collided > .8 && jumppower >= 5)) {
7848 if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile)) {
7849 for (int k = 0; k < numenvsounds; k++) {
7850 if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) {
7851 aitype = attacktypecutoff;
7856 if (!Person::players[0]->dead &&
7857 losupdatedelay < 0 &&
7858 !Game::editorenabled &&
7860 ((!Tutorial::active || cananger) && hostile)) {
7861 losupdatedelay = .2;
7862 if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) {
7863 aitype = attacktypecutoff;
7866 if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight) {
7867 //TODO: factor out canSeePlayer()
7868 if (distsq(&coords, &Person::players[0]->coords) < 400) {
7869 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
7870 if ((Object::checkcollide(
7871 DoRotation(jointPos(head), 0, yaw, 0) *
7874 DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0) *
7875 Person::players[0]->scale +
7876 Person::players[0]->coords) == -1) ||
7877 (Person::players[0]->animTarget == hanganim && normaldotproduct(Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) {
7878 /* //TODO: changed j to 0 on a whim, make sure this is correct
7879 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
7880 Person::players[j]->facing,coords-Person::players[j]->coords)<0)
7882 aitype = attacktypecutoff;
7890 if (lastseentime < 0) {
7891 //aitype=passivetype;
7893 aitype = pathfindtype;
7894 finalfinaltarget = waypoints[waypoint];
7895 finalpathfindpoint = -1;
7896 targetpathfindpoint = -1;
7897 lastpathfindpoint = -1;
7898 lastpathfindpoint2 = -1;
7899 lastpathfindpoint3 = -1;
7900 lastpathfindpoint4 = -1;
7904 if (aitype != gethelptype) {
7908 //get help from buddies
7909 if (aitype == gethelptype) {
7910 runninghowlong += multiplier;
7911 aiupdatedelay -= multiplier;
7913 if (aiupdatedelay < 0 || ally == 0) {
7917 //TODO: factor out closest search somehow
7920 float closestdist = -1;
7921 for (unsigned k = 0; k < Person::players.size(); k++) {
7922 if ((k != id) && (k != 0) && !Person::players[k]->dead &&
7923 (Person::players[k]->howactive < typedead1) &&
7924 !Person::players[k]->skeleton.free &&
7925 (Person::players[k]->aitype == passivetype)) {
7926 float distance = distsq(&coords, &Person::players[k]->coords);
7927 if (closestdist == -1 || distance < closestdist) {
7928 closestdist = distance;
7933 if (closest != -1) {
7938 lastseen = Person::players[0]->coords;
7944 XYZ facing = coords;
7945 XYZ flatfacing = Person::players[ally]->coords;
7946 facing.y += jointPos(head).y * scale;
7947 flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale;
7948 if (-1 != Object::checkcollide(facing, flatfacing)) {
7952 //no available ally, run back to player
7954 Person::players[ally]->skeleton.free ||
7955 Person::players[ally]->aitype != passivetype ||
7956 lastseentime <= 0) {
7957 aitype = searchtype;
7963 targetyaw = roughDirectionTo(coords, Person::players[ally]->coords);
7964 lookyaw = targetyaw;
7965 aiupdatedelay = .05;
7968 if (distsqflat(&coords, &Person::players[ally]->coords) < 3) {
7969 aitype = searchtype;
7971 Person::players[ally]->aitype = searchtype;
7972 if (Person::players[ally]->lastseentime < lastseentime) {
7973 Person::players[ally]->lastseen = lastseen;
7974 Person::players[ally]->lastseentime = lastseentime;
7975 Person::players[ally]->lastchecktime = lastchecktime;
7979 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7980 if (!avoidsomething) {
7981 targetyaw += 90 * (whichdirection * 2 - 1);
7983 XYZ leftpos, rightpos;
7984 float leftdist, rightdist;
7985 leftpos = coords + DoRotation(facing, 0, 90, 0);
7986 rightpos = coords - DoRotation(facing, 0, 90, 0);
7987 leftdist = distsq(&leftpos, &avoidwhere);
7988 rightdist = distsq(&rightpos, &avoidwhere);
7989 if (leftdist < rightdist) {
8004 if (collided < 1 || animTarget != jumpupanim) {
8007 if (collided > .8 && jumppower >= 5) {
8012 //retreiving a weapon on the ground
8013 if (aitype == getweapontype) {
8014 aiupdatedelay -= multiplier;
8015 lastchecktime -= multiplier;
8017 if (aiupdatedelay < 0) {
8023 float closestdist = -1;
8024 for (unsigned k = 0; k < weapons.size(); k++) {
8025 if (weapons[k].owner == -1) {
8026 float distance = distsq(&coords, &weapons[k].position);
8027 if (closestdist == -1 || distance < closestdist) {
8028 closestdist = distance;
8033 if (closest != -1) {
8042 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile)) {
8043 if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) {
8044 aitype = attacktypecutoff;
8048 if (!Person::players[0]->dead) {
8050 if (weapons[ally].owner != -1 ||
8051 distsq(&coords, &weapons[ally].position) > 16) {
8052 aitype = attacktypecutoff;
8055 //TODO: factor these out as moveToward()
8056 targetyaw = roughDirectionTo(coords, weapons[ally].position);
8057 lookyaw = targetyaw;
8058 aiupdatedelay = .05;
8061 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8062 if (!avoidsomething) {
8063 targetyaw += 90 * (whichdirection * 2 - 1);
8065 XYZ leftpos, rightpos;
8066 float leftdist, rightdist;
8067 leftpos = coords + DoRotation(facing, 0, 90, 0);
8068 rightpos = coords - DoRotation(facing, 0, 90, 0);
8069 leftdist = distsq(&leftpos, &avoidwhere);
8070 rightdist = distsq(&rightpos, &avoidwhere);
8071 if (leftdist < rightdist) {
8087 if (animTarget != crouchremoveknifeanim &&
8088 animTarget != removeknifeanim) {
8089 throwtogglekeydown = 0;
8093 if (collided < 1 || animTarget != jumpupanim) {
8096 if ((collided > .8 && jumppower >= 5)) {
8101 if (aitype == attacktypecutoff) {
8102 aiupdatedelay -= multiplier;
8103 //dodge or reverse rabbit kicks, knife throws, flips
8104 if (damage < damagetolerance * 2 / 3) {
8105 if ((Person::players[0]->animTarget == rabbitkickanim ||
8106 Person::players[0]->animTarget == knifethrowanim ||
8107 (Person::players[0]->isFlip() &&
8108 normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) &&
8109 !Person::players[0]->skeleton.free &&
8110 (aiupdatedelay < .1)) {
8115 if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
8116 if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
8117 if (isIdle() || isCrouch() || isRun() || isFlip()) {
8118 if (abs(Random() % 2) == 0) {
8119 setTargetAnimation(backhandspringanim);
8121 setTargetAnimation(rollanim);
8123 targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
8126 if (animTarget == jumpupanim || animTarget == jumpdownanim) {
8127 setTargetAnimation(flipanim);
8132 aiupdatedelay = .02;
8135 //get confused by flips
8136 if (Person::players[0]->isFlip() &&
8137 !Person::players[0]->skeleton.free &&
8138 Person::players[0]->animTarget != walljumprightkickanim &&
8139 Person::players[0]->animTarget != walljumpleftkickanim) {
8140 if (distsq(&Person::players[0]->coords, &coords) < 25) {
8141 if ((1 - damage / damagetolerance) > .5) {
8146 //go for weapon on the ground
8147 if (wentforweapon < 3) {
8148 for (unsigned k = 0; k < weapons.size(); k++) {
8149 if (creature != wolftype) {
8150 if (num_weapons == 0 &&
8151 weapons[k].owner == -1 &&
8152 weapons[k].velocity.x == 0 &&
8153 weapons[k].velocity.z == 0 &&
8154 weapons[k].velocity.y == 0) {
8155 if (distsq(&coords, &weapons[k].position) < 16) {
8158 aitype = getweapontype;
8165 //dodge/reverse walljump kicks
8166 if (damage < damagetolerance / 2) {
8167 if (Animation::animations[animTarget].height != highheight) {
8168 if (damage < damagetolerance * .5 &&
8169 ((Person::players[0]->animTarget == walljumprightkickanim ||
8170 Person::players[0]->animTarget == walljumpleftkickanim) &&
8171 ((aiupdatedelay < .15 &&
8173 (aiupdatedelay < .08 &&
8174 difficulty != 2)))) {
8179 //walked off a ledge (?)
8180 if (isRun() && !onground) {
8181 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
8182 XYZ test2 = coords + facing;
8184 XYZ test = coords + facing;
8186 j = Object::checkcollide(test2, test, laststanding);
8188 j = Object::checkcollide(test2, test);
8192 setTargetAnimation(getStop());
8195 aitype = pathfindtype;
8196 finalfinaltarget = waypoints[waypoint];
8197 finalpathfindpoint = -1;
8198 targetpathfindpoint = -1;
8199 lastpathfindpoint = -1;
8200 lastpathfindpoint2 = -1;
8201 lastpathfindpoint3 = -1;
8202 lastpathfindpoint4 = -1;
8208 //lose sight of player in the air (?)
8209 if (Person::players[0]->coords.y > coords.y + 5 &&
8210 Animation::animations[Person::players[0]->animTarget].height != highheight &&
8211 !Person::players[0]->onterrain) {
8212 aitype = pathfindtype;
8213 finalfinaltarget = waypoints[waypoint];
8214 finalpathfindpoint = -1;
8215 targetpathfindpoint = -1;
8216 lastpathfindpoint = -1;
8217 lastpathfindpoint2 = -1;
8218 lastpathfindpoint3 = -1;
8219 lastpathfindpoint4 = -1;
8221 //it's time to think (?)
8222 if (aiupdatedelay < 0 &&
8223 !Animation::animations[animTarget].attack &&
8224 animTarget != staggerbackhighanim &&
8225 animTarget != staggerbackhardanim &&
8226 animTarget != backhandspringanim &&
8227 animTarget != dodgebackanim) {
8229 if (weaponactive == -1 && num_weapons > 0) {
8230 drawkeydown = Random() % 2;
8234 rabbitkickenabled = Random() % 2;
8236 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
8237 XYZ targetpoint = Person::players[0]->coords;
8238 float vellength = findLength(&velocity);
8239 if (vellength != 0 &&
8240 distsq(&Person::players[0]->coords, &coords) < distsq(&rotatetarget, &coords)) {
8241 targetpoint += Person::players[0]->velocity *
8242 findDistance(&Person::players[0]->coords, &coords) / vellength;
8244 targetyaw = roughDirectionTo(coords, targetpoint);
8245 lookyaw = targetyaw;
8246 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
8248 if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1)) {
8250 } else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
8251 distsq(&coords, &Person::players[0]->coords) < 9) &&
8252 Person::players[0]->weaponactive != -1) {
8254 } else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0)) {
8259 //chill out around the corpse
8260 if (Person::players[0]->dead) {
8262 if (Random() % 10 == 0) {
8265 if (Random() % 100 == 0) {
8266 aitype = pathfindtype;
8267 finalfinaltarget = waypoints[waypoint];
8268 finalpathfindpoint = -1;
8269 targetpathfindpoint = -1;
8270 lastpathfindpoint = -1;
8271 lastpathfindpoint2 = -1;
8272 lastpathfindpoint3 = -1;
8273 lastpathfindpoint4 = -1;
8282 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8283 targetyaw += 90 * (whichdirection * 2 - 1);
8286 if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype) {
8291 if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7) {
8296 if (aitype != playercontrolled &&
8301 for (unsigned j = 0; j < Person::players.size(); j++) {
8302 if (j != id && !Person::players[j]->skeleton.free &&
8303 Person::players[j]->hasvictim &&
8304 (Tutorial::active && reversaltrain ||
8305 Random() % 2 == 0 && difficulty == 2 ||
8306 Random() % 4 == 0 && difficulty == 1 ||
8307 Random() % 8 == 0 && difficulty == 0 ||
8308 Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
8309 Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
8310 (Random() % 2 == 0 || difficulty == 2) ||
8311 (isIdle() || isRun()) &&
8312 Person::players[j]->weaponactive != -1 ||
8313 Person::players[j]->animTarget == swordslashanim &&
8314 weaponactive != -1 ||
8315 Person::players[j]->animTarget == staffhitanim ||
8316 Person::players[j]->animTarget == staffspinhitanim)) {
8317 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
8318 Person::players[j]->victim == Person::players[id] &&
8319 (Person::players[j]->animTarget == sweepanim ||
8320 Person::players[j]->animTarget == spinkickanim ||
8321 Person::players[j]->animTarget == staffhitanim ||
8322 Person::players[j]->animTarget == staffspinhitanim ||
8323 Person::players[j]->animTarget == winduppunchanim ||
8324 Person::players[j]->animTarget == upunchanim ||
8325 Person::players[j]->animTarget == wolfslapanim ||
8326 Person::players[j]->animTarget == knifeslashstartanim ||
8327 Person::players[j]->animTarget == swordslashanim &&
8328 (distsq(&Person::players[j]->coords, &coords) < 2 ||
8329 weaponactive != -1))) {
8339 Person::players[target]->Reverse();
8346 if (collided > .8 && jumppower >= 5 ||
8347 distsq(&coords, &Person::players[0]->coords) > 400 &&
8349 creature == rabbittype) {
8352 //TODO: why are we controlling the human?
8353 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
8354 Person::players[0]->jumpkeydown = 0;
8356 if (Person::players[0]->animTarget == jumpdownanim &&
8357 distsq(&Person::players[0]->coords, &coords) < 40) {
8364 if (Tutorial::active) {
8370 XYZ facing = coords;
8371 XYZ flatfacing = Person::players[0]->coords;
8372 facing.y += jointPos(head).y * scale;
8373 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
8374 if (occluded >= 2) {
8375 if (-1 != Object::checkcollide(facing, flatfacing)) {
8379 if (lastseentime <= 0 &&
8380 (creature != wolftype ||
8381 weaponstuck == -1)) {
8382 aitype = searchtype;
8384 lastseen = Person::players[0]->coords;
8393 if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
8394 (aitype == attacktypecutoff ||
8395 aitype == searchtype)) {
8396 if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
8397 XYZ test = Person::players[0]->coords;
8399 if (-1 == Object::checkcollide(Person::players[0]->coords, test)) {
8405 if (aitype == passivetype && !(numwaypoints > 1) ||
8407 pause && damage > superpermanentdamage) {
8426 XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0);
8427 facing = flatfacing;
8429 if (aitype == attacktypecutoff) {
8430 targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
8431 targetheadpitch = pitchTo(coords, Person::players[0]->coords);
8432 } else if (howactive >= typesleeping) {
8433 targetheadyaw = targetyaw;
8434 targetheadpitch = 0;
8436 if (interestdelay <= 0) {
8437 interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
8438 headtarget = coords;
8439 headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
8440 headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
8441 headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
8442 headtarget += facing * 1.5;
8444 targetheadyaw = 180 - roughDirectionTo(coords, headtarget);
8445 targetheadpitch = pitchTo(coords, headtarget);