2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2017 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
21 #include "Objects/Person.hpp"
23 #include "Animation/Animation.hpp"
24 #include "Audio/Sounds.hpp"
25 #include "Audio/openal_wrapper.hpp"
27 #include "Level/Awards.hpp"
28 #include "Level/Dialog.hpp"
29 #include "Tutorial.hpp"
30 #include "Utils/Folders.hpp"
32 extern float multiplier;
33 extern Terrain terrain;
35 extern int environment;
37 extern FRUSTUM frustum;
39 extern float realmultiplier;
41 extern float slomodelay;
42 extern bool cellophane;
43 extern float texdetail;
44 extern float realtexdetail;
45 extern int bloodtoggle;
46 extern bool autoslomo;
47 extern float camerashake;
49 extern float viewdistance;
50 extern float blackout;
51 extern int difficulty;
52 extern bool decalstoggle;
53 extern float fadestart;
55 extern bool winfreeze;
56 extern bool showpoints;
57 extern bool immediate;
58 extern float smoketex;
59 extern bool reversaltrain;
60 extern bool canattack;
62 extern float damagedealt;
64 extern float hostiletime;
66 extern bool gamestarted;
68 extern XYZ envsound[30];
69 extern float envsoundvol[30];
70 extern int numenvsounds;
71 extern float envsoundlife[30];
73 extern XYZ windvector;
75 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
80 , animCurrent(bounceidleanim)
81 , animTarget(bounceidleanim)
88 , howactive(typeactive)
90 , superruntoggle(false)
124 , rabbitkickenabled(false)
138 , superpermanentdamage(0)
181 , normalsupdatedelay(0)
185 , forwardkeydown(false)
186 , forwardstogglekeydown(false)
187 , rightkeydown(false)
191 , jumptogglekeydown(false)
192 , crouchkeydown(false)
193 , crouchtogglekeydown(false)
195 , drawtogglekeydown(false)
196 , throwkeydown(false)
197 , throwtogglekeydown(false)
198 , attackkeydown(false)
220 , whichdirection(false)
221 , whichdirectiondelay(0)
222 , avoidsomething(false)
232 , lefthandmorphness(0)
233 , righthandmorphness(0)
237 , targetlefthandmorphness(0)
238 , targetrighthandmorphness(0)
239 , targetheadmorphness(1)
240 , targetchestmorphness(0)
241 , targettailmorphness(0)
242 , lefthandmorphstart(0)
243 , lefthandmorphend(0)
244 , righthandmorphstart(0)
245 , righthandmorphend(0)
255 , highreversaldelay(0)
256 , lowreversaldelay(0)
305 , weaponstuckwhere(0)
318 , finalpathfindpoint(0)
319 , targetpathfindpoint(0)
320 , lastpathfindpoint(0)
321 , lastpathfindpoint2(0)
322 , lastpathfindpoint3(0)
323 , lastpathfindpoint4(0)
343 , neckspurtparticledelay(0)
348 , rabbitkickragdoll(false)
356 setProportions(1, 1, 1, 1);
359 /* Read a person in tfile. Throws an error if it’s not valid */
360 Person::Person(FILE* tfile, int mapvers, unsigned i)
364 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
366 funpackf(tfile, "Bi", &howactive);
368 howactive = typeactive;
371 funpackf(tfile, "Bf", &scale);
376 funpackf(tfile, "Bb", &immobile);
381 funpackf(tfile, "Bf", &yaw);
386 if (num_weapons < 0 || num_weapons > 5) {
387 throw InvalidPersonException();
389 if (num_weapons > 0 && num_weapons < 5) {
390 for (int j = 0; j < num_weapons; j++) {
391 weaponids[j] = weapons.size();
393 funpackf(tfile, "Bi", &type);
394 weapons.push_back(Weapon(type, id));
397 funpackf(tfile, "Bi", &numwaypoints);
398 for (int j = 0; j < numwaypoints; j++) {
399 funpackf(tfile, "Bf", &waypoints[j].x);
400 funpackf(tfile, "Bf", &waypoints[j].y);
401 funpackf(tfile, "Bf", &waypoints[j].z);
403 funpackf(tfile, "Bi", &waypointtype[j]);
405 waypointtype[j] = wpkeepwalking;
409 funpackf(tfile, "Bi", &waypoint);
410 if (waypoint > (numwaypoints - 1)) {
414 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
415 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
416 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
417 funpackf(tfile, "Bf Bf", &power, &speedmult);
420 funpackf(tfile, "Bf Bf Bf Bf", &proportions[0], &proportions[1], &proportions[2], &proportions[3]);
422 setProportions(1, 1, 1, 1);
425 funpackf(tfile, "Bi", &numclothes);
426 for (int k = 0; k < numclothes; k++) {
428 funpackf(tfile, "Bi", &templength);
429 for (int l = 0; l < templength; l++) {
430 funpackf(tfile, "Bb", &clothes[k][l]);
432 clothes[k][templength] = '\0';
433 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
439 if (creature == wolftype) {
441 damagetolerance = 300;
448 realoldcoords = coords;
451 void Person::skeletonLoad(bool clothes)
455 PersonType::types[creature].figureFileName,
456 PersonType::types[creature].lowFigureFileName,
457 PersonType::types[creature].clothesFileName,
458 PersonType::types[creature].modelFileNames[0],
459 PersonType::types[creature].modelFileNames[1],
460 PersonType::types[creature].modelFileNames[2],
461 PersonType::types[creature].modelFileNames[3],
462 PersonType::types[creature].modelFileNames[4],
463 PersonType::types[creature].modelFileNames[5],
464 PersonType::types[creature].modelFileNames[6],
465 PersonType::types[creature].lowModelFileName,
466 PersonType::types[creature].modelClothesFileName,
469 skeleton.drawmodel.textureptr.load(PersonType::types[creature].skins[whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
472 void Person::setProportions(float head, float body, float arms, float legs)
474 proportions[0] = head;
475 proportions[1] = body;
476 proportions[2] = arms;
477 proportions[3] = legs;
480 XYZ Person::getProportion(int part) const
482 XYZ prop = PersonType::types[creature].proportions[part] * proportions[part];
492 * GameTick/doPlayerCollisions
494 void Person::CheckKick()
496 if (!(hasvictim && (animTarget == rabbitkickanim && victim && victim != this->shared_from_this() && frameCurrent >= 2 && animCurrent == rabbitkickanim) && distsq(&coords, &victim->coords) < 1.2 && !victim->skeleton.free)) {
500 if (Animation::animations[victim->animTarget].height != lowheight) {
501 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
502 XYZ relative = velocity;
504 Normalise(&relative);
508 if (!Tutorial::active) {
509 emit_sound_at(heavyimpactsound, victim->coords);
512 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
513 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
516 victim->DoDamage(100 * damagemult / victim->protectionhigh);
523 animTarget = backflipanim;
525 velocity = facing * -10;
529 resume_stream(whooshsound);
532 award_bonus(id, cannon);
533 } else if (victim->isCrouch()) {
534 animTarget = rabbitkickreversedanim;
535 animCurrent = rabbitkickreversedanim;
536 victim->animCurrent = rabbitkickreversalanim;
537 victim->animTarget = rabbitkickreversalanim;
543 victim->oldcoords = victim->coords;
544 coords = victim->coords;
545 victim->targetyaw = targetyaw;
546 victim->victim = this->shared_from_this();
553 * GameTick::doPlayerCollisions - spread fire between players
554 * GameTick::ProcessDevKeys - press f to ignite
555 * Person::DoStuff - spread fire from lit campfires and bushes
557 void Person::CatchFire()
559 XYZ flatfacing, flatvelocity;
561 for (int i = 0; i < 10; i++) {
562 howmany = fabs(Random() % (skeleton.joints.size()));
564 flatvelocity = skeleton.joints[howmany].velocity;
565 flatfacing = skeleton.joints[howmany].position * scale + coords;
567 flatvelocity = velocity;
568 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
570 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
575 emit_sound_at(firestartsound, coords);
577 emit_stream_at(stream_firesound, coords);
585 * idle animation for this creature (depending on status)
587 int Person::getIdle()
589 if (Dialog::inDialog() && (howactive == typeactive) && PersonType::types[creature].hasAnimTalkIdle()) {
590 return PersonType::types[creature].animTalkIdle;
592 if (hasvictim && (victim != this->shared_from_this())) {
593 if ((!victim->dead && victim->aitype != passivetype &&
594 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
595 victim->id < Person::players.size())) {
596 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
597 return PersonType::types[creature].animFightIdle;
599 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
600 if (weapons[weaponids[weaponactive]].getType() == knife) {
601 return knifefightidleanim;
603 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1) {
604 return swordfightidlebothanim;
606 if (weapons[weaponids[weaponactive]].getType() == sword) {
607 return swordfightidleanim;
609 if (weapons[weaponids[weaponactive]].getType() == staff) {
610 return swordfightidleanim;
613 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause) {
614 return fightsidestep;
618 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype) {
621 if (howactive == typesitting) {
624 if (howactive == typesittingwall) {
627 if (howactive == typesleeping) {
630 if (howactive == typedead1) {
633 if (howactive == typedead2) {
636 if (howactive == typedead3) {
639 if (howactive == typedead4) {
642 return PersonType::types[creature].animBounceIdle;
646 * crouch animation for this creature
648 int Person::getCrouch()
650 return PersonType::types[creature].animCrouch;
654 * running animation for this creature (can be upright or all fours)
658 if (superruntoggle && (weaponactive == -1)) {
659 return PersonType::types[creature].animRunning;
661 return PersonType::types[creature].animRun;
667 int Person::getStop()
669 return PersonType::types[creature].animStop;
674 int Person::getLanding()
676 return PersonType::types[creature].animLanding;
681 int Person::getLandhard()
683 return PersonType::types[creature].animLandingHard;
689 * Person::DoAnimations
692 SolidHitBonus(int playerid)
694 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo) {
695 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
697 award_bonus(playerid, solidhit);
702 * spawns blood effects
704 void Person::DoBlood(float howmuch, int which)
706 // FIXME: should abstract out inputs
707 static int bleedxint, bleedyint;
709 if (bloodtoggle && !Tutorial::active) {
710 if (bleeding <= 0 && spurt) {
712 for (int i = 0; i < 3; i++) {
713 // emit blood particles
716 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
717 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
718 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
719 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
722 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
723 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
724 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
725 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
728 if (Random() % 2 == 0) { // 50% chance
729 for (int i = 0; i < 3; i++) {
730 if (Random() % 2 != 0) {
731 // emit teeth particles
734 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
735 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
738 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
739 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
743 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
745 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
747 Sprite::setLastSpriteSpecial(3); // sets it to teeth
753 // FIXME: manipulating attributes
754 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
757 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) {
758 bleedxint = abs(Random() % 512);
759 bleedyint = abs(Random() % 512);
763 bleedy /= realtexdetail;
764 bleedx /= realtexdetail;
765 direction = abs(Random() % 2) * 2 - 1;
774 * spawns big blood effects and ???
775 * modifies character's skin texture
777 void Person::DoBloodBig(float howmuch, int which)
779 static int bleedxint, bleedyint, i, j;
781 if (howmuch && id == 0) {
785 if (!Tutorial::active || id == 0) {
786 if (aitype != playercontrolled && howmuch > 0) {
790 if (creature == wolftype) {
791 int i = abs(Random() % 2);
793 whichsound = snarlsound;
796 whichsound = snarl2sound;
799 if (creature == rabbittype) {
800 int i = abs(Random() % 2);
802 whichsound = rabbitpainsound;
804 if (i == 1 && howmuch >= 2) {
805 whichsound = rabbitpain1sound;
809 if (whichsound != -1) {
810 emit_sound_at(whichsound, coords);
816 if (id == 0 && howmuch > 0) {
820 if (bloodtoggle && decalstoggle && !Tutorial::active) {
821 if (bleeding <= 0 && spurt) {
823 for (int i = 0; i < 3; i++) {
824 // emit blood particles
825 // FIXME: copypaste from above
828 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
829 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
830 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
831 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
834 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
835 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
836 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
837 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
842 // weird texture manipulation code follows.
843 // looks like this is painting blood onto the character's skin texture
844 // FIXME: surely there's a better way
846 int offsetx = 0, offsety = 0;
848 offsety = Random() % 40;
849 offsetx = abs(Random() % 60);
851 if (which == 190 || which == 185) {
852 offsety = Random() % 40;
853 offsetx = abs(Random() % 100) - 20;
856 offsety = Random() % 10;
857 offsetx = Random() % 10;
860 offsety = Random() % 20;
861 offsetx = Random() % 20;
863 if (which == 220 || which == 215) {
872 for (i = 0; i < 512; i++) {
873 for (j = 0; j < 512; j++) {
874 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) {
902 if (endx > 512 - 1) {
905 if (endy > 512 - 1) {
915 startx /= realtexdetail;
916 starty /= realtexdetail;
917 endx /= realtexdetail;
918 endy /= realtexdetail;
920 int texdetailint = realtexdetail;
922 for (i = startx; i < endx; i++) {
923 for (j = starty; j < endy; j++) {
924 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) {
925 color = Random() % 85 + 170;
926 where = i * skeleton.skinsize * 3 + j * 3;
927 if (skeleton.skinText[where + 0] > color / 2) {
928 skeleton.skinText[where + 0] = color / 2;
930 skeleton.skinText[where + 1] = 0;
931 skeleton.skinText[where + 2] = 0;
935 skeleton.drawmodel.textureptr.bind();
940 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) {
941 bleedxint = abs(Random() % 512);
942 bleedyint = abs(Random() % 512);
944 bleedy = bleedxint + offsetx;
945 bleedx = bleedyint + offsety;
946 bleedy /= realtexdetail;
947 bleedx /= realtexdetail;
954 if (bleedx > skeleton.skinsize - 1) {
955 bleedx = skeleton.skinsize - 1;
957 if (bleedy > skeleton.skinsize - 1) {
958 bleedy = skeleton.skinsize - 1;
960 direction = abs(Random() % 2) * 2 - 1;
962 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
963 deathbleeding += bleeding;
964 bloodloss += bleeding * 3;
966 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
967 if (abs(Random() % 2) == 0) {
968 aitype = gethelptype;
971 aitype = attacktypecutoff;
981 * similar to DoBloodBig
983 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
987 static XYZ startpoint, endpoint, colpoint, movepoint;
988 static float rotationpoint;
990 static XYZ p1, p2, p3, p0;
993 float coordsx, coordsy;
996 if (bloodtoggle && decalstoggle && !Tutorial::active) {
998 if (!skeleton.free) {
999 where = DoRotation(where, 0, -yaw, 0);
1003 startpoint.y += 100;
1008 // ray testing for a tri in the character model
1009 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
1010 if (whichtri != -1) {
1011 // low level geometry math
1013 p1 = skeleton.drawmodel.getTriangleVertex(whichtri, 0);
1014 p2 = skeleton.drawmodel.getTriangleVertex(whichtri, 1);
1015 p3 = skeleton.drawmodel.getTriangleVertex(whichtri, 2);
1017 bary.x = distsq(&p0, &p1);
1018 bary.y = distsq(&p0, &p2);
1019 bary.z = distsq(&p0, &p3);
1021 total = bary.x + bary.y + bary.z;
1026 bary.x = 1 - bary.x;
1027 bary.y = 1 - bary.y;
1028 bary.z = 1 - bary.z;
1030 total = bary.x + bary.y + bary.z;
1035 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1036 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1037 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1038 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1039 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1040 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1041 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;
1042 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;
1044 if (bleeding <= 0 && spurt) {
1046 for (int i = 0; i < 3; i++) {
1047 // emit blood particles
1048 // FIXME: more copypaste code
1050 if (skeleton.free) {
1051 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1052 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1053 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1054 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1057 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1058 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1059 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1060 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1065 // texture manipulation follows
1067 int offsetx = 0, offsety = 0;
1068 offsetx = (1 + coordsy) * 512 - 291;
1069 offsety = coordsx * 512 - 437;
1076 for (i = 0; i < 512; i++) {
1077 for (j = 0; j < 512; j++) {
1078 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) {
1105 if (endx > 512 - 1) {
1108 if (endy > 512 - 1) {
1111 if (endx < startx) {
1114 if (endy < starty) {
1118 startx /= realtexdetail;
1119 starty /= realtexdetail;
1120 endx /= realtexdetail;
1121 endy /= realtexdetail;
1123 int texdetailint = realtexdetail;
1125 for (i = startx; i < endx; i++) {
1126 for (j = starty; j < endy; j++) {
1127 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) {
1128 color = Random() % 85 + 170;
1129 where = i * skeleton.skinsize * 3 + j * 3;
1130 if (skeleton.skinText[where + 0] > color / 2) {
1131 skeleton.skinText[where + 0] = color / 2;
1133 skeleton.skinText[where + 1] = 0;
1134 skeleton.skinText[where + 2] = 0;
1135 } 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) {
1136 color = Random() % 85 + 170;
1137 where = i * skeleton.skinsize * 3 + j * 3;
1138 if (skeleton.skinText[where + 0] > color / 2) {
1139 skeleton.skinText[where + 0] = color / 2;
1141 skeleton.skinText[where + 1] = 0;
1142 skeleton.skinText[where + 2] = 0;
1146 skeleton.drawmodel.textureptr.bind();
1149 bleedy = (1 + coordsy) * 512;
1150 bleedx = coordsx * 512;
1151 bleedy /= realtexdetail;
1152 bleedx /= realtexdetail;
1159 if (bleedx > skeleton.skinsize - 1) {
1160 bleedx = skeleton.skinsize - 1;
1162 if (bleedy > skeleton.skinsize - 1) {
1163 bleedy = skeleton.skinsize - 1;
1165 direction = abs(Random() % 2) * 2 - 1;
1167 if (whichtri == -1) {
1171 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1172 deathbleeding += bleeding;
1173 bloodloss += bleeding * 3;
1175 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1176 if (abs(Random() % 2) == 0) {
1177 aitype = gethelptype;
1180 aitype = attacktypecutoff;
1191 * guessing this performs a reversal
1193 void Person::Reverse()
1195 if (!((victim->aitype == playercontrolled || hostiletime > 1 || staggerdelay <= 0) && victim->animTarget != jumpupanim && victim->animTarget != jumpdownanim && (!Tutorial::active || cananger) && hostile)) {
1199 if (normaldotproduct(victim->facing, victim->coords - coords) > 0 && (victim->id != 0 || difficulty >= 2) && (creature != wolftype || victim->creature == wolftype)) {
1203 if (animTarget == sweepanim) {
1204 animTarget = sweepreversedanim;
1205 animCurrent = sweepreversedanim;
1206 victim->animCurrent = sweepreversalanim;
1207 victim->animTarget = sweepreversalanim;
1209 if (animTarget == spinkickanim) {
1210 animTarget = spinkickreversedanim;
1211 animCurrent = spinkickreversedanim;
1212 victim->animCurrent = spinkickreversalanim;
1213 victim->animTarget = spinkickreversalanim;
1215 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1216 if (animTarget == rabbittacklinganim) {
1219 victim->frameCurrent = 6;
1220 victim->frameTarget = 7;
1222 animTarget = upunchreversedanim;
1223 animCurrent = upunchreversedanim;
1224 victim->animCurrent = upunchreversalanim;
1225 victim->animTarget = upunchreversalanim;
1227 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1228 if (victim->weaponactive != -1) {
1229 victim->throwtogglekeydown = 1;
1230 XYZ tempVelocity = victim->velocity * .2;
1231 if (tempVelocity.x == 0) {
1232 tempVelocity.x = .1;
1234 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1235 victim->num_weapons--;
1236 if (victim->num_weapons) {
1237 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1238 if (victim->weaponstuck == victim->num_weapons) {
1239 victim->weaponstuck = 0;
1243 victim->weaponactive = -1;
1244 for (unsigned j = 0; j < Person::players.size(); j++) {
1245 Person::players[j]->wentforweapon = 0;
1249 animTarget = staffhitreversedanim;
1250 animCurrent = staffhitreversedanim;
1251 victim->animCurrent = staffhitreversalanim;
1252 victim->animTarget = staffhitreversalanim;
1254 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1255 if (victim->weaponactive != -1) {
1256 victim->throwtogglekeydown = 1;
1257 XYZ tempVelocity = victim->velocity * .2;
1258 if (tempVelocity.x == 0) {
1259 tempVelocity.x = .1;
1261 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1262 victim->num_weapons--;
1263 if (victim->num_weapons) {
1264 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1265 if (victim->weaponstuck == victim->num_weapons) {
1266 victim->weaponstuck = 0;
1270 victim->weaponactive = -1;
1271 for (unsigned j = 0; j < Person::players.size(); j++) {
1272 Person::players[j]->wentforweapon = 0;
1275 animTarget = staffspinhitreversedanim;
1276 animCurrent = staffspinhitreversedanim;
1277 victim->animCurrent = staffspinhitreversalanim;
1278 victim->animTarget = staffspinhitreversalanim;
1280 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1281 if (victim->weaponactive != -1) {
1282 victim->throwtogglekeydown = 1;
1283 XYZ tempVelocity = victim->velocity * .2;
1284 if (tempVelocity.x == 0) {
1285 tempVelocity.x = .1;
1287 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1288 victim->num_weapons--;
1289 if (victim->num_weapons) {
1290 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1291 if (victim->weaponstuck == victim->num_weapons) {
1292 victim->weaponstuck = 0;
1296 victim->weaponactive = -1;
1297 for (unsigned j = 0; j < Person::players.size(); j++) {
1298 Person::players[j]->wentforweapon = 0;
1301 animTarget = swordslashreversedanim;
1302 animCurrent = swordslashreversedanim;
1303 victim->animCurrent = swordslashreversalanim;
1304 victim->animTarget = swordslashreversalanim;
1306 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1307 if (victim->weaponactive != -1) {
1308 victim->throwtogglekeydown = 1;
1309 XYZ tempVelocity = victim->velocity * .2;
1310 if (tempVelocity.x == 0) {
1311 tempVelocity.x = .1;
1313 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1314 victim->num_weapons--;
1315 if (victim->num_weapons) {
1316 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1317 if (victim->weaponstuck == victim->num_weapons) {
1318 victim->weaponstuck = 0;
1322 victim->weaponactive = -1;
1323 for (unsigned j = 0; j < Person::players.size(); j++) {
1324 Person::players[j]->wentforweapon = 0;
1327 animTarget = knifeslashreversedanim;
1328 animCurrent = knifeslashreversedanim;
1329 victim->animCurrent = knifeslashreversalanim;
1330 victim->animTarget = knifeslashreversalanim;
1332 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1333 victim->targettilt2 = targettilt2;
1334 victim->frameCurrent = frameCurrent;
1335 victim->frameTarget = frameTarget;
1336 victim->target = target;
1337 victim->velocity = 0;
1338 victim->oldcoords = victim->coords;
1339 victim->coords = coords;
1340 victim->targetyaw = targetyaw;
1341 victim->yaw = targetyaw;
1342 victim->victim = this->shared_from_this();
1344 if (animTarget == winduppunchanim) {
1345 animTarget = winduppunchblockedanim;
1346 victim->animTarget = blockhighleftanim;
1347 victim->frameTarget = 1;
1348 victim->target = .5;
1349 victim->victim = this->shared_from_this();
1350 victim->targetyaw = targetyaw + 180;
1352 if (animTarget == wolfslapanim) {
1353 animTarget = winduppunchblockedanim;
1354 victim->animTarget = blockhighleftanim;
1355 victim->frameTarget = 1;
1356 victim->target = .5;
1357 victim->victim = this->shared_from_this();
1358 victim->targetyaw = targetyaw + 180;
1360 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1361 animTarget = swordslashparriedanim;
1362 parriedrecently = .4;
1363 victim->parriedrecently = 0;
1364 victim->animTarget = swordslashparryanim;
1365 victim->frameTarget = 1;
1366 victim->target = .5;
1367 victim->victim = this->shared_from_this();
1368 victim->targetyaw = targetyaw + 180;
1370 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1371 if (victim->weaponactive != -1) {
1372 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1373 if (weapons[victim->weaponids[0]].getType() == staff) {
1374 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1376 if (weapons[weaponids[0]].getType() == staff) {
1377 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1379 emit_sound_at(swordstaffsound, victim->coords);
1381 emit_sound_at(metalhitsound, victim->coords);
1385 victim->Puff(righthand);
1387 victim->frameTarget = 0;
1388 victim->animTarget = staggerbackhighanim;
1389 victim->targetyaw = targetyaw + 180;
1391 aim = DoRotation(facing, 0, 90, 0) * 21;
1393 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1394 victim->num_weapons--;
1395 if (victim->num_weapons) {
1396 victim->weaponids[0] = victim->weaponids[num_weapons];
1397 if (victim->weaponstuck == victim->num_weapons) {
1398 victim->weaponstuck = 0;
1401 victim->weaponactive = -1;
1402 for (unsigned i = 0; i < Person::players.size(); i++) {
1403 Person::players[i]->wentforweapon = 0;
1407 if (abs(Random() % 20) == 0) {
1408 if (weaponactive != -1) {
1409 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1410 if (weapons[victim->weaponids[0]].getType() == staff) {
1411 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1413 if (weapons[weaponids[0]].getType() == staff) {
1414 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1417 emit_sound_at(swordstaffsound, coords);
1419 emit_sound_at(metalhitsound, coords);
1427 animTarget = staggerbackhighanim;
1428 targetyaw = targetyaw + 180;
1430 aim = DoRotation(facing, 0, 90, 0) * 21;
1432 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1435 weaponids[0] = weaponids[num_weapons];
1436 if (weaponstuck == num_weapons) {
1441 for (unsigned i = 0; i < Person::players.size(); i++) {
1442 Person::players[i]->wentforweapon = 0;
1447 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1448 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1449 victim->animTarget = dodgebackanim;
1450 victim->frameTarget = 0;
1454 rotatetarget = coords - victim->coords;
1455 Normalise(&rotatetarget);
1456 victim->targetyaw = -asin(0 - rotatetarget.x);
1457 victim->targetyaw *= 360 / 6.28;
1458 if (rotatetarget.z < 0) {
1459 victim->targetyaw = 180 - victim->targetyaw;
1462 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1464 victim->lastattack3 = victim->lastattack2;
1465 victim->lastattack2 = victim->lastattack;
1466 victim->lastattack = victim->animTarget;
1468 victim->animTarget = sweepanim;
1469 victim->frameTarget = 0;
1473 rotatetarget = coords - victim->coords;
1474 Normalise(&rotatetarget);
1475 victim->targetyaw = -asin(0 - rotatetarget.x);
1476 victim->targetyaw *= 360 / 6.28;
1477 if (rotatetarget.z < 0) {
1478 victim->targetyaw = 180 - victim->targetyaw;
1481 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1483 victim->lastattack3 = victim->lastattack2;
1484 victim->lastattack2 = victim->lastattack;
1485 victim->lastattack = victim->animTarget;
1491 victim->velocity = 0;
1493 if (aitype != playercontrolled) {
1495 if (escapednum < 2) {
1496 int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
1497 if ((Random() % chances) == 0) {
1503 if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal) {
1511 void Person::DoDamage(float howmuch)
1515 damagetaken += howmuch / power;
1517 damagedealt += howmuch / power;
1521 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo)) {
1526 if (!Tutorial::active) {
1527 damage += howmuch / power;
1528 permanentdamage += howmuch / 2 / power;
1529 superpermanentdamage += howmuch / 4 / power;
1532 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2) {
1535 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt) {
1540 camerashake += howmuch / 100;
1541 if ((howmuch > 50 && damage > damagetolerance / 2)) {
1542 blackout = damage / damagetolerance;
1550 if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile)) {
1551 aitype = attacktypecutoff;
1553 if (!Tutorial::active && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1554 if (abs(Random() % 2) == 0) {
1555 aitype = gethelptype;
1558 aitype = attacktypecutoff;
1563 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1566 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1567 if (skeleton.free) {
1568 flatvelocity2 = skeleton.joints[i].velocity;
1569 flatfacing2 = skeleton.joints[i].position * scale + coords;
1571 flatvelocity2 = velocity;
1572 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1574 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1575 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1576 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1577 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1578 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1579 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1582 emit_sound_at(splattersound, coords);
1587 if (!dead && creature == wolftype) {
1588 award_bonus(0, Wolfbonus);
1595 if (!Tutorial::active || id == 0) {
1596 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1597 int whichsound = -1;
1599 if (creature == wolftype) {
1600 int i = abs(Random() % 2);
1602 whichsound = snarlsound;
1605 whichsound = snarl2sound;
1608 if (creature == rabbittype) {
1609 int i = abs(Random() % 2);
1611 whichsound = rabbitpainsound;
1613 if (i == 1 && damage > damagetolerance) {
1614 whichsound = rabbitpain1sound;
1618 if (whichsound != -1) {
1619 emit_sound_at(whichsound, coords);
1620 addEnvSound(coords);
1628 * calculate/animate head facing direction?
1630 void Person::DoHead()
1632 static XYZ rotatearound;
1634 static float lookspeed = 500;
1636 if (!freeze && !winfreeze) {
1639 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1640 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1642 while (targetheadyaw > 180) {
1643 targetheadyaw -= 360;
1645 while (targetheadyaw < -180) {
1646 targetheadyaw += 360;
1649 if (targetheadyaw > 160) {
1650 targetheadpitch = targetheadpitch * -1;
1652 if (targetheadyaw < -160) {
1653 targetheadpitch = targetheadpitch * -1;
1655 if (targetheadyaw > 160) {
1656 targetheadyaw = targetheadyaw - 180;
1658 if (targetheadyaw < -160) {
1659 targetheadyaw = targetheadyaw + 180;
1662 if (targetheadpitch > 120) {
1663 targetheadpitch = 120;
1665 if (targetheadpitch < -120) {
1666 targetheadpitch = -120;
1668 if (targetheadyaw > 120) {
1669 targetheadyaw = 120;
1671 if (targetheadyaw < -120) {
1672 targetheadyaw = -120;
1676 targetheadpitch = 0;
1679 if (targetheadyaw > 80) {
1682 if (targetheadyaw < -80) {
1683 targetheadyaw = -80;
1685 if (targetheadpitch > 50) {
1686 targetheadpitch = 50;
1688 if (targetheadpitch < -50) {
1689 targetheadpitch = -50;
1693 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed) {
1694 headyaw = targetheadyaw;
1695 } else if (headyaw > targetheadyaw) {
1696 headyaw -= multiplier * lookspeed;
1697 } else if (headyaw < targetheadyaw) {
1698 headyaw += multiplier * lookspeed;
1701 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2) {
1702 headpitch = targetheadpitch;
1703 } else if (headpitch > targetheadpitch) {
1704 headpitch -= multiplier * lookspeed / 2;
1705 } else if (headpitch < targetheadpitch) {
1706 headpitch += multiplier * lookspeed / 2;
1709 rotatearound = jointPos(neck);
1710 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1714 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1715 facing = DoRotation(facing, headpitch * .4, 0, 0);
1716 facing = DoRotation(facing, 0, headyaw * .4, 0);
1719 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1720 facing = DoRotation(facing, headpitch * .8, 0, 0);
1721 facing = DoRotation(facing, 0, headyaw * .8, 0);
1724 if (animTarget == walkanim) {
1725 facing = DoRotation(facing, headpitch * .6, 0, 0);
1726 facing = DoRotation(facing, 0, headyaw * .6, 0);
1729 skeleton.specialforward[0] = facing;
1730 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1731 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
1732 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1733 skeleton.FindRotationMuscle(i, animTarget);
1740 * ragdolls character?
1742 void Person::RagDoll(bool checkcollision)
1747 if (!skeleton.free) {
1751 if (id == 0 && isFlip()) {
1759 facing = DoRotation(facing, 0, yaw, 0);
1761 skeleton.freetime = 0;
1763 skeleton.longdead = 0;
1766 skeleton.broken = 0;
1767 skeleton.spinny = 1;
1769 skeleton.freefall = 1;
1771 if (!isnormal(velocity.x)) {
1774 if (!isnormal(velocity.y)) {
1777 if (!isnormal(velocity.z)) {
1780 if (!isnormal(yaw)) {
1783 if (!isnormal(coords.x)) {
1786 if (!isnormal(tilt)) {
1789 if (!isnormal(tilt2)) {
1793 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1794 skeleton.joints[i].delay = 0;
1795 skeleton.joints[i].locked = 0;
1796 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1797 if (!isnormal(skeleton.joints[i].position.x)) {
1798 skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1800 if (!isnormal(skeleton.joints[i].position.x)) {
1801 skeleton.joints[i].position = coords;
1803 skeleton.joints[i].position.y += .1;
1804 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1805 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1808 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1809 skeleton.joints[i].velocity = 0;
1810 skeleton.joints[i].velchange = 0;
1812 skeleton.DoConstraints(&coords, &scale);
1813 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
1814 skeleton.DoConstraints(&coords, &scale);
1815 skeleton.DoConstraints(&coords, &scale);
1816 skeleton.DoConstraints(&coords, &scale);
1817 skeleton.DoConstraints(&coords, &scale);
1820 speed = targetFrame().speed * 2;
1821 if (currentFrame().speed > targetFrame().speed) {
1822 speed = currentFrame().speed * 2;
1825 speed = transspeed * 2;
1830 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1831 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height) {
1832 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);
1834 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1836 change.x = (float)(Random() % 100) / 100;
1837 change.y = (float)(Random() % 100) / 100;
1838 change.z = (float)(Random() % 100) / 100;
1839 skeleton.joints[i].velocity += change;
1840 skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change;
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].velchange += change;
1846 skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change;
1849 if (checkcollision) {
1852 if (!skeleton.joints.empty()) {
1855 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1856 average += skeleton.joints[j].position;
1858 average /= skeleton.joints.size();
1859 coords += average * scale;
1860 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1861 skeleton.joints[j].position -= average;
1865 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1866 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1867 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
1868 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1871 if (SphereCheck(&lowpoint, 3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
1872 coords.x = lowpoint.x;
1873 coords.z = lowpoint.z;
1882 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1883 velocity += skeleton.joints[i].velocity * scale;
1885 velocity /= skeleton.joints.size();
1888 if (Random() % 2 == 0) {
1889 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1890 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1891 weapons[weaponids[0]].velocity.x += .01;
1894 weaponids[0] = weaponids[num_weapons];
1895 if (weaponstuck == num_weapons) {
1900 for (unsigned i = 0; i < Person::players.size(); i++) {
1901 Person::players[i]->wentforweapon = 0;
1906 animTarget = bounceidleanim;
1907 animCurrent = bounceidleanim;
1915 void Person::FootLand(bodypart whichfoot, float opacity)
1917 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
1918 cerr << "FootLand called on wrong bodypart" << endl;
1921 static XYZ terrainlight;
1922 static XYZ footvel, footpoint;
1923 if (opacity >= 1 || skiddelay <= 0) {
1926 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1927 if (distsq(&footpoint, &viewer)) {
1928 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1930 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1931 footvel = velocity / 5;
1932 if (footvel.y < .8) {
1935 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1936 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1937 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1938 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1939 if (environment == snowyenvironment) {
1940 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1942 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1944 } else if (environment == grassyenvironment) {
1945 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1946 } else if (environment == desertenvironment) {
1947 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1949 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1953 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
1954 footvel = velocity / 5;
1955 if (footvel.y < .8) {
1958 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1959 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1960 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1967 * make a puff effect at a body part (dust effect?)
1969 void Person::Puff(int whichlabel)
1971 static XYZ footvel, footpoint;
1974 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1975 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1979 * I think I added this in an attempt to clean up code
1981 void Person::setTargetAnimation(int animation)
1983 animTarget = animation;
1992 void Person::DoAnimations()
1994 if (!skeleton.free) {
1995 static float oldtarget;
1997 if (isIdle() && animCurrent != getIdle()) {
1998 normalsupdatedelay = 0;
2001 if (animTarget == tempanim || animCurrent == tempanim) {
2002 Animation::animations[tempanim] = tempanimation;
2004 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
2011 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
2012 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
2014 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z)) {
2017 if (!crouchkeydown && velocity.y >= -15) {
2021 if ((animCurrent == jumpupanim || animTarget == jumpdownanim) /*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
2026 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
2028 if (normaldotproduct(targfacing, velocity) >= -.3) {
2029 animTarget = flipanim;
2031 animTarget = backflipanim;
2033 crouchtogglekeydown = 1;
2042 if (Animation::animations[animTarget].attack != reversed) {
2045 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
2046 crouchtogglekeydown = 0;
2047 if (aitype == playercontrolled) {
2051 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain)) {
2055 crouchtogglekeydown = 1;
2059 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
2061 normalsupdatedelay = 0;
2066 if (animTarget == rollanim && frameTarget == 3 && onfire) {
2068 emit_sound_at(fireendsound, coords);
2069 pause_sound(stream_firesound);
2073 if (animTarget == rabbittacklinganim && frameTarget == 1) {
2074 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0) {
2077 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
2078 if (normaldotproduct(victim->facing, facing) > 0) {
2079 victim->animTarget = rabbittackledbackanim;
2081 victim->animTarget = rabbittackledfrontanim;
2083 victim->frameTarget = 2;
2086 victim->targetyaw = yaw;
2087 if (victim->aitype == gethelptype) {
2088 victim->DoDamage(victim->damagetolerance - victim->damage);
2090 //victim->DoDamage(30);
2091 if (creature == wolftype) {
2093 emit_sound_at(clawslicesound, victim->coords);
2095 victim->DoBloodBig(1 / victim->armorhead, 210);
2097 award_bonus(id, TackleBonus,
2098 victim->aitype == gethelptype ? 50 : 0);
2102 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2103 if (weapons[weaponids[0]].getType() == knife) {
2104 if (weaponactive == -1) {
2106 } else if (weaponactive == 0) {
2110 if (weaponactive == -1) {
2111 emit_sound_at(knifesheathesound, coords);
2113 if (weaponactive != -1) {
2114 emit_sound_at(knifedrawsound, coords, 128);
2117 drawtogglekeydown = 1;
2120 if (!Tutorial::active || id == 0) {
2121 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2122 int whichsound = -1;
2124 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2125 if (targetFrame().label == 1) {
2126 whichsound = footstepsound;
2128 whichsound = footstepsound2;
2130 if (targetFrame().label == 1) {
2131 FootLand(leftfoot, 1);
2133 if (targetFrame().label == 2) {
2134 FootLand(rightfoot, 1);
2136 if (targetFrame().label == 3 && isRun()) {
2137 FootLand(rightfoot, 1);
2138 FootLand(leftfoot, 1);
2141 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2142 if (targetFrame().label == 1) {
2143 whichsound = footstepsound3;
2145 whichsound = footstepsound4;
2150 if (targetFrame().label == 1) {
2151 whichsound = footstepsound3;
2153 whichsound = footstepsound4;
2156 if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2157 if (Animation::animations[animTarget].attack != neutral) {
2158 unsigned r = abs(Random() % 3);
2160 whichsound = lowwhooshsound;
2163 whichsound = midwhooshsound;
2166 whichsound = highwhooshsound;
2169 if (Animation::animations[animTarget].attack == neutral) {
2170 whichsound = movewhooshsound;
2172 } else if (targetFrame().label == 4) {
2173 whichsound = knifeswishsound;
2175 if (targetFrame().label == 8 && !Tutorial::active) {
2176 whichsound = landsound2;
2179 if (whichsound != -1) {
2180 emit_sound_at(whichsound, coords, 256.);
2183 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2184 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2185 addEnvSound(coords, 15);
2187 addEnvSound(coords, 6);
2192 if (targetFrame().label == 3) {
2194 emit_sound_at(whichsound, coords, 128.);
2201 if (!Tutorial::active || id == 0) {
2202 if (speechdelay <= 0) {
2203 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
2204 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2205 int whichsound = -1;
2206 if (targetFrame().label == 4 && aitype != playercontrolled) {
2207 if (Animation::animations[animTarget].attack != neutral) {
2208 unsigned r = abs(Random() % 4);
2209 whichsound = PersonType::types[creature].soundsAttack[r];
2214 if (whichsound != -1) {
2215 emit_sound_at(whichsound, coords);
2222 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2223 FootLand(leftfoot, 1);
2224 FootLand(rightfoot, 1);
2228 currentoffset = targetoffset;
2229 frameTarget = frameCurrent;
2230 animCurrent = animTarget;
2233 if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2234 for (unsigned i = 0; i < weapons.size(); i++) {
2235 if (weapons[i].owner == -1) {
2236 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2237 if (distsq(&coords, &weapons[i].position) >= 1) {
2238 if (weapons[i].getType() != staff) {
2239 emit_sound_at(knifedrawsound, coords, 128.);
2249 if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2250 for (unsigned i = 0; i < weapons.size(); i++) {
2251 bool willwork = true;
2252 if (weapons[i].owner != -1) {
2253 if (Person::players[weapons[i].owner]->weaponstuck != -1) {
2254 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i)) {
2255 if (Person::players[weapons[i].owner]->num_weapons > 1) {
2261 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free)) {
2262 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2263 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2264 bool fleshstuck = false;
2265 if (weapons[i].owner != -1) {
2266 if (victim->weaponstuck != -1) {
2267 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2273 emit_sound_at(fleshstabremovesound, coords, 128.);
2275 if (weapons[i].getType() != staff) {
2276 emit_sound_at(knifedrawsound, coords, 128.);
2279 if (weapons[i].owner != -1) {
2280 victim = Person::players[weapons[i].owner];
2281 if (victim->num_weapons == 1) {
2282 victim->num_weapons = 0;
2284 victim->num_weapons = 1;
2287 //victim->weaponactive=-1;
2288 victim->skeleton.longdead = 0;
2289 victim->skeleton.free = 1;
2290 victim->skeleton.broken = 0;
2292 for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) {
2293 victim->skeleton.joints[j].velchange = 0;
2294 victim->skeleton.joints[j].locked = 0;
2300 Normalise(&relative);
2301 XYZ footvel, footpoint;
2303 footpoint = weapons[i].position;
2304 if (victim->weaponstuck != -1) {
2305 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2307 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2309 weapons[i].bloody = 2;
2310 weapons[i].blooddrip = 5;
2311 victim->weaponstuck = -1;
2314 if (victim->num_weapons > 0) {
2315 if (victim->weaponstuck != 0 && victim->weaponstuck != -1) {
2316 victim->weaponstuck = 0;
2318 if (victim->weaponids[0] == int(i)) {
2319 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2323 victim->jointVel(abdomen) += relative * 6;
2324 victim->jointVel(neck) += relative * 6;
2325 victim->jointVel(rightshoulder) += relative * 6;
2326 victim->jointVel(leftshoulder) += relative * 6;
2335 if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2336 if (weaponactive == -1) {
2338 } else if (weaponactive == 0) {
2340 if (num_weapons == 2) {
2342 buffer = weaponids[0];
2343 weaponids[0] = weaponids[1];
2344 weaponids[1] = buffer;
2347 if (weaponactive == -1) {
2348 emit_sound_at(knifesheathesound, coords, 128.);
2350 if (weaponactive != -1) {
2351 emit_sound_at(knifedrawsound, coords, 128.);
2355 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2356 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2357 Normalise(&rotatetarget);
2358 targetyaw = -asin(0 - rotatetarget.x);
2359 targetyaw *= 360 / 6.28;
2360 if (rotatetarget.z < 0) {
2361 targetyaw = 180 - targetyaw;
2364 if (animTarget == walljumprightkickanim) {
2367 if (animTarget == walljumpleftkickanim) {
2374 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0)) {
2378 if (distsq(&victim->coords, &/*Person::players[i]->*/ coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1) {
2386 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2387 animTarget = rabbittackleanim;
2389 emit_sound_at(jumpsound, coords);
2397 targetloc = velocity;
2398 Normalise(&targetloc);
2399 targetloc += coords;
2400 for (unsigned i = 0; i < Person::players.size(); i++) {
2402 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2403 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2408 if (closestid != -1) {
2409 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2411 victim = Person::players[closestid];
2412 coords = victim->coords;
2413 animCurrent = rabbittacklinganim;
2414 animTarget = rabbittacklinganim;
2418 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2419 rotatetarget = coords - victim->coords;
2420 Normalise(&rotatetarget);
2421 targetyaw = -asin(0 - rotatetarget.x);
2422 targetyaw *= 360 / 6.28;
2423 if (rotatetarget.z < 0) {
2424 targetyaw = 180 - targetyaw;
2427 if (animTarget != rabbitrunninganim) {
2428 emit_sound_at(jumpsound, coords, 128.);
2435 float damagemult = 1 * power;
2436 if (creature == wolftype) {
2437 damagemult = 2.5 * power;
2440 damagemult /= victim->damagetolerance / 200;
2442 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)) {
2443 if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2444 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2449 if (Random() % 2 || creature == wolftype) {
2452 if (creature == wolftype) {
2456 if (!Tutorial::active) {
2457 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2459 if (creature == wolftype) {
2460 emit_sound_at(clawslicesound, victim->coords, 128.);
2462 victim->DoBloodBig(2 / victim->armorhead, 175);
2466 relative = victim->coords - coords;
2468 Normalise(&relative);
2469 relative = DoRotation(relative, 0, -90, 0);
2470 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2471 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2473 victim->jointVel(head) += relative * damagemult * 200;
2475 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2481 if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2482 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2487 if (Random() % 2 || creature == wolftype) {
2489 if (creature == wolftype) {
2493 emit_sound_at(whooshhitsound, victim->coords);
2494 if (creature == wolftype) {
2495 emit_sound_at(clawslicesound, victim->coords, 128.);
2497 victim->DoBloodBig(2, 175);
2501 relative = victim->coords - coords;
2503 Normalise(&relative);
2505 Normalise(&relative);
2506 relative = DoRotation(relative, 0, 90, 0);
2507 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2508 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2510 victim->jointVel(head) += relative * damagemult * 100;
2512 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2516 if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2517 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2524 if (!Tutorial::active) {
2525 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2527 if (creature == wolftype) {
2528 emit_sound_at(clawslicesound, victim->coords, 128.);
2530 victim->DoBloodBig(2 / victim->armorhead, 175);
2536 Normalise(&relative);
2537 relative = DoRotation(relative, 0, -90, 0);
2538 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2539 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2541 victim->jointVel(head) += relative * damagemult * 200;
2543 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2545 if (victim->damage > victim->damagetolerance) {
2546 award_bonus(id, style);
2553 if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2554 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2561 if (!Tutorial::active) {
2562 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2564 if (creature == wolftype) {
2565 emit_sound_at(clawslicesound, victim->coords, 128.);
2567 victim->DoBloodBig(2 / victim->armorhead, 175);
2573 Normalise(&relative);
2574 relative = DoRotation(relative, 0, 90, 0);
2575 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2576 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2578 victim->jointVel(head) += relative * damagemult * 200;
2580 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2582 if (victim->damage > victim->damagetolerance) {
2583 award_bonus(id, style);
2590 if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2591 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2600 emit_sound_at(whooshhitsound, victim->coords);
2603 relative = victim->coords - coords;
2605 Normalise(&relative);
2606 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2607 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2609 victim->jointVel(head) += relative * damagemult * 100;
2611 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2615 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
2616 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2621 emit_sound_at(whooshhitsound, victim->coords, 128.);
2623 victim->skeleton.longdead = 0;
2624 victim->skeleton.free = 1;
2625 victim->skeleton.broken = 0;
2626 victim->skeleton.spinny = 1;
2628 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2629 victim->skeleton.joints[i].velchange = 0;
2630 victim->skeleton.joints[i].delay = 0;
2631 victim->skeleton.joints[i].locked = 0;
2632 //victim->skeleton.joints[i].velocity=0;
2638 Normalise(&relative);
2639 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2640 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2641 victim->skeleton.joints[i].position.y += relative.y * .3;
2642 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2643 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2645 victim->Puff(abdomen);
2646 victim->jointVel(abdomen).y = relative.y * 400;
2650 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2651 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2656 if (!Tutorial::active) {
2657 emit_sound_at(heavyimpactsound, coords, 128.);
2660 relative = victim->coords - coords;
2662 Normalise(&relative);
2663 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2664 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2666 victim->Puff(abdomen);
2667 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2671 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2672 victim->jointVel(abdomen) += relative * damagemult * 300;
2676 if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
2677 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2682 if (!Tutorial::active) {
2683 emit_sound_at(thudsound, coords);
2686 victim->skeleton.longdead = 0;
2687 victim->skeleton.free = 1;
2688 victim->skeleton.broken = 0;
2689 victim->skeleton.spinny = 1;
2691 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2692 victim->skeleton.joints[i].velchange = 0;
2693 //victim->skeleton.joints[i].delay=0;
2694 victim->skeleton.joints[i].locked = 0;
2697 relative = victim->coords - coords;
2698 Normalise(&relative);
2700 Normalise(&relative);
2701 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2702 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2704 if (!victim->dead) {
2708 victim->Puff(abdomen);
2709 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2710 victim->jointVel(abdomen) += relative * damagemult * 200;
2712 if (!victim->dead) {
2718 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2721 if (!victim->skeleton.free) {
2727 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2728 emit_sound_at(knifesheathesound, coords, 128.);
2731 if (victim && hasvictim) {
2732 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2734 XYZ where, startpoint, endpoint, movepoint, colpoint;
2735 float rotationpoint;
2737 if (weapons[weaponids[weaponactive]].getType() == knife) {
2738 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2739 where -= victim->coords;
2740 if (!victim->skeleton.free) {
2741 where = DoRotation(where, 0, -victim->yaw, 0);
2745 startpoint.y += 100;
2749 if (weapons[weaponids[weaponactive]].getType() == sword) {
2750 where = weapons[weaponids[weaponactive]].position;
2751 where -= victim->coords;
2752 if (!victim->skeleton.free) {
2753 where = DoRotation(where, 0, -victim->yaw, 0);
2756 where = weapons[weaponids[weaponactive]].tippoint;
2757 where -= victim->coords;
2758 if (!victim->skeleton.free) {
2759 where = DoRotation(where, 0, -victim->yaw, 0);
2763 if (weapons[weaponids[weaponactive]].getType() == staff) {
2764 where = weapons[weaponids[weaponactive]].position;
2765 where -= victim->coords;
2766 if (!victim->skeleton.free) {
2767 where = DoRotation(where, 0, -victim->yaw, 0);
2770 where = weapons[weaponids[weaponactive]].tippoint;
2771 where -= victim->coords;
2772 if (!victim->skeleton.free) {
2773 where = DoRotation(where, 0, -victim->yaw, 0);
2779 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2781 if (whichtri != -1) {
2782 if (victim->dead != 2) {
2783 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2784 if (!victim->dead) {
2785 award_bonus(id, FinishedBonus);
2789 weapons[weaponids[weaponactive]].bloody = 2;
2792 victim->skeleton.longdead = 0;
2793 victim->skeleton.free = 1;
2794 victim->skeleton.broken = 0;
2796 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2797 victim->skeleton.joints[i].velchange = 0;
2798 victim->skeleton.joints[i].locked = 0;
2799 //victim->skeleton.joints[i].velocity=0;
2801 emit_sound_at(fleshstabsound, coords, 128);
2803 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2804 weapons[weaponids[weaponactive]].blooddrip += 5;
2805 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2807 if (whichtri == -1) {
2809 emit_sound_at(knifesheathesound, coords, 128.);
2815 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
2817 emit_sound_at(knifedrawsound, coords, 128);
2820 if (victim && hasvictim) {
2821 XYZ footvel, footpoint;
2823 emit_sound_at(fleshstabremovesound, coords, 128.);
2826 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2828 if (weapons[weaponids[weaponactive]].getType() == sword) {
2829 XYZ where, startpoint, endpoint, movepoint;
2830 float rotationpoint;
2833 where = weapons[weaponids[weaponactive]].position;
2834 where -= victim->coords;
2835 if (!victim->skeleton.free) {
2836 where = DoRotation(where, 0, -victim->yaw, 0);
2839 where = weapons[weaponids[weaponactive]].tippoint;
2840 where -= victim->coords;
2841 if (!victim->skeleton.free) {
2842 where = DoRotation(where, 0, -victim->yaw, 0);
2848 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2849 footpoint += victim->coords;
2851 if (whichtri == -1) {
2852 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2855 if (weapons[weaponids[weaponactive]].getType() == staff) {
2856 XYZ where, startpoint, endpoint, movepoint;
2857 float rotationpoint;
2860 where = weapons[weaponids[weaponactive]].position;
2861 where -= victim->coords;
2862 if (!victim->skeleton.free) {
2863 where = DoRotation(where, 0, -victim->yaw, 0);
2866 where = weapons[weaponids[weaponactive]].tippoint;
2867 where -= victim->coords;
2868 if (!victim->skeleton.free) {
2869 where = DoRotation(where, 0, -victim->yaw, 0);
2875 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2876 footpoint += victim->coords;
2878 if (whichtri == -1) {
2879 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2882 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2884 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2885 victim->skeleton.longdead = 0;
2886 victim->skeleton.free = 1;
2887 victim->skeleton.broken = 0;
2889 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2890 victim->skeleton.joints[i].velchange = 0;
2891 victim->skeleton.joints[i].locked = 0;
2892 //victim->skeleton.joints[i].velocity=0;
2898 Normalise(&relative);
2899 //victim->Puff(abdomen);
2901 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2904 if (victim->bloodloss < victim->damagetolerance) {
2905 victim->bloodloss += 1000;
2909 victim->jointVel(abdomen) += relative * damagemult * 20;
2913 if (!hasvictim && onterrain) {
2914 weapons[weaponids[weaponactive]].bloody = 0;
2915 weapons[weaponids[weaponactive]].blooddrip = 0;
2919 if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2920 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2929 if (!Tutorial::active) {
2930 emit_sound_at(heavyimpactsound, victim->coords, 128);
2935 relative = victim->coords - coords;
2937 Normalise(&relative);
2938 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2939 victim->skeleton.joints[i].velocity = relative * 30;
2941 victim->jointVel(head) += relative * damagemult * 150;
2943 victim->frameTarget = 0;
2944 victim->animTarget = staggerbackhardanim;
2945 victim->targetyaw = targetyaw + 180;
2947 victim->stunned = 1;
2950 victim->Puff(abdomen);
2951 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2957 if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2958 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2963 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
2964 if (!Tutorial::active) {
2965 emit_sound_at(thudsound, victim->coords);
2967 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
2968 if (!Tutorial::active) {
2969 emit_sound_at(whooshhitsound, victim->coords);
2972 if (!Tutorial::active) {
2973 emit_sound_at(heavyimpactsound, victim->coords);
2977 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight) {
2981 relative = victim->coords - coords;
2983 Normalise(&relative);
2985 Normalise(&relative);
2986 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2987 victim->skeleton.joints[i].velocity = relative * 5;
2989 victim->jointVel(abdomen) += relative * damagemult * 400;
2991 victim->frameTarget = 0;
2992 victim->animTarget = staggerbackhardanim;
2993 victim->targetyaw = targetyaw + 180;
2995 victim->stunned = 1;
2997 victim->Puff(abdomen);
2998 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
3004 if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3005 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3006 if (victim->id == 0) {
3009 emit_sound_at(landsound2, victim->coords);
3015 if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3016 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3017 if (victim->id == 0) {
3021 if (weaponactive != -1) {
3022 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3023 if (weapons[victim->weaponids[0]].getType() == staff) {
3024 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3026 if (weapons[weaponids[0]].getType() == staff) {
3027 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3030 emit_sound_at(swordstaffsound, victim->coords);
3032 emit_sound_at(metalhitsound, victim->coords);
3040 if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3041 if (weaponactive != -1) {
3044 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);
3046 weapons[weaponids[0]].thrown(aim * 50);
3049 weaponids[0] = weaponids[num_weapons];
3055 if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3057 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 && /*Animation::animations[victim->animTarget].height!=lowheight&&*/ victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
3059 if (!Tutorial::active) {
3060 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
3063 award_bonus(id, Slicebonus);
3064 if (!Tutorial::active) {
3065 emit_sound_at(knifeslicesound, victim->coords);
3067 //victim->jointVel(abdomen)+=relative*damagemult*200;
3068 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
3069 if (victim->id != 0 || difficulty == 2) {
3070 victim->frameTarget = 0;
3071 victim->animTarget = staggerbackhardanim;
3072 victim->targetyaw = targetyaw + 180;
3076 victim->lowreversaldelay = 0;
3077 victim->highreversaldelay = 0;
3078 if (aitype != playercontrolled) {
3079 weaponmissdelay = .6;
3082 if (!Tutorial::active) {
3083 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3084 weapons[weaponids[weaponactive]].bloody = 1;
3086 weapons[weaponids[weaponactive]].blooddrip += 3;
3089 XYZ footvel, footpoint;
3091 if (skeleton.free) {
3092 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3094 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3096 if (Tutorial::active) {
3097 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
3100 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
3102 footvel = DoRotation(facing, 0, 90, 0) * .8;
3103 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3104 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3105 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3106 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3108 victim->DoDamage(damagemult * 0);
3112 if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3113 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
3114 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
3115 award_bonus(id, Slashbonus);
3117 if (!Tutorial::active) {
3118 if (normaldotproduct(victim->facing, victim->coords - coords) < 0) {
3119 victim->DoBloodBig(2 / victim->armorhigh, 190);
3121 victim->DoBloodBig(2 / victim->armorhigh, 185);
3123 victim->deathbleeding = 1;
3124 emit_sound_at(swordslicesound, victim->coords);
3125 victim->frameTarget = 0;
3126 victim->animTarget = staggerbackhardanim;
3127 victim->targetyaw = targetyaw + 180;
3129 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3130 weapons[weaponids[weaponactive]].bloody = 1;
3132 weapons[weaponids[weaponactive]].blooddrip += 3;
3134 float bloodlossamount;
3135 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
3136 victim->bloodloss += bloodlossamount / victim->armorhigh;
3137 victim->DoDamage(damagemult * 0);
3139 XYZ footvel, footpoint;
3141 if (skeleton.free) {
3142 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3144 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3147 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3149 footvel = DoRotation(facing, 0, 90, 0) * .8;
3151 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3152 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3153 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3154 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3157 if (victim->weaponactive != -1) {
3158 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3159 if (weapons[victim->weaponids[0]].getType() == staff) {
3160 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3162 if (weapons[weaponids[0]].getType() == staff) {
3163 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3166 emit_sound_at(swordstaffsound, victim->coords);
3168 emit_sound_at(metalhitsound, victim->coords);
3173 victim->Puff(righthand);
3175 victim->frameTarget = 0;
3176 victim->animTarget = staggerbackhighanim;
3177 victim->targetyaw = targetyaw + 180;
3179 aim = DoRotation(facing, 0, 90, 0) * 21;
3181 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3182 victim->num_weapons--;
3183 if (victim->num_weapons) {
3184 victim->weaponids[0] = victim->weaponids[num_weapons];
3185 if (victim->weaponstuck == victim->num_weapons) {
3186 victim->weaponstuck = 0;
3189 victim->weaponactive = -1;
3190 for (unsigned i = 0; i < Person::players.size(); i++) {
3191 Person::players[i]->wentforweapon = 0;
3197 if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3198 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3199 if (!Tutorial::active) {
3200 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3205 if (Random() % 2 || creature == wolftype) {
3208 emit_sound_at(staffheadsound, victim->coords);
3212 relative = victim->coords - coords;
3214 Normalise(&relative);
3215 relative = DoRotation(relative, 0, 90, 0);
3217 Normalise(&relative);
3218 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3219 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3221 victim->jointVel(head) += relative * damagemult * 230;
3222 victim->jointVel(neck) += relative * damagemult * 230;
3224 if (!Tutorial::active) {
3225 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3227 award_bonus(id, solidhit, 30);
3232 if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3233 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3234 if (!Tutorial::active) {
3235 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3240 if (Random() % 2 || creature == wolftype) {
3243 emit_sound_at(staffheadsound, victim->coords);
3247 relative = victim->coords - coords;
3249 Normalise(&relative);
3250 relative = DoRotation(relative, 0, -90, 0);
3251 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3252 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3254 victim->jointVel(head) += relative * damagemult * 220;
3255 victim->jointVel(neck) += relative * damagemult * 220;
3257 if (!Tutorial::active) {
3258 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3260 award_bonus(id, solidhit, 60);
3265 if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3266 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3268 if (!Tutorial::active) {
3269 if (!victim->dead) {
3270 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3275 if (Random() % 2 || creature == wolftype) {
3278 emit_sound_at(staffbodysound, victim->coords);
3280 victim->skeleton.longdead = 0;
3281 victim->skeleton.free = 1;
3282 victim->skeleton.broken = 0;
3284 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3285 victim->skeleton.joints[i].velchange = 0;
3286 victim->skeleton.joints[i].locked = 0;
3287 //victim->skeleton.joints[i].velocity=0;
3294 Normalise(&relative);
3295 if (!victim->dead) {
3296 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3297 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3299 victim->jointVel(abdomen) += relative * damagemult * 40;
3302 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3303 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3306 victim->Puff(abdomen);
3307 if (!Tutorial::active) {
3308 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3310 if (!victim->dead) {
3311 award_bonus(id, solidhit, 40);
3317 if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3318 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3324 relative = victim->coords - coords;
3326 Normalise(&relative);
3330 if (Animation::animations[victim->animTarget].height == lowheight) {
3336 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3337 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3339 victim->jointVel(head) += relative * damagemult * 200;
3340 if (!Tutorial::active) {
3341 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3344 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3345 if (victim->howactive == typesleeping) {
3346 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3348 if (creature == wolftype) {
3349 emit_sound_at(clawslicesound, victim->coords, 128.);
3351 victim->DoBloodBig(2 / victim->armorhead, 175);
3354 if (victim->damage >= victim->damagetolerance) {
3357 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3358 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3360 victim->jointVel(abdomen) += relative * damagemult * 200;
3361 victim->frameTarget = 0;
3362 victim->animTarget = staggerbackhighanim;
3363 victim->targetyaw = targetyaw + 180;
3365 if (!Tutorial::active) {
3366 emit_sound_at(landsound2, victim->coords, 128.);
3368 victim->Puff(abdomen);
3369 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3370 if (creature == wolftype) {
3371 emit_sound_at(clawslicesound, victim->coords, 128.);
3373 victim->DoBloodBig(2 / victim->armorhigh, 170);
3379 if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3380 if ((victim->animTarget != jumpupanim) &&
3381 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3382 (victim != this->shared_from_this())) {
3387 if (!Tutorial::active) {
3388 emit_sound_at(landsound2, victim->coords, 128.);
3391 relative = victim->coords - coords;
3393 Normalise(&relative);
3395 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3398 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3399 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3401 relative = DoRotation(relative, 0, -90, 0);
3403 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3404 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) {
3405 victim->skeleton.joints[i].velocity = relative * 80;
3408 victim->Puff(rightankle);
3409 victim->Puff(leftankle);
3410 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3412 if (victim->damage >= victim->damagetolerance) {
3415 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3416 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3418 relative = DoRotation(relative, 0, -90, 0);
3419 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3420 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) {
3421 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3424 victim->jointVel(abdomen) += relative * damagemult * 200;
3425 victim->frameTarget = 0;
3426 victim->animTarget = staggerbackhighanim;
3427 victim->targetyaw = targetyaw + 180;
3429 if (!Tutorial::active) {
3430 emit_sound_at(landsound2, victim->coords, 128.);
3432 victim->Puff(abdomen);
3433 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3440 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3441 if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3450 if (!Tutorial::active) {
3451 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3453 if (creature == wolftype) {
3454 emit_sound_at(clawslicesound, victim->coords, 128);
3456 victim->DoBloodBig(2 / victim->armorhigh, 170);
3460 relative = victim->coords - oldcoords;
3462 Normalise(&relative);
3463 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3464 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3466 victim->jointVel(abdomen) += relative * damagemult * 200;
3467 victim->Puff(abdomen);
3468 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3470 award_bonus(id, Reversal);
3473 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3474 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3475 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3476 takeWeapon(victim->weaponids[victim->weaponactive]);
3477 victim->num_weapons--;
3478 if (victim->num_weapons > 0) {
3479 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3481 victim->weaponactive = -1;
3486 if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3495 emit_sound_at(whooshhitsound, victim->coords, 128.);
3498 relative = victim->coords - oldcoords;
3500 Normalise(&relative);
3501 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3502 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3504 victim->jointVel(abdomen) += relative * damagemult * 200;
3506 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3509 if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3519 award_bonus(id, staffreversebonus);
3521 if (!Tutorial::active) {
3522 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3525 award_bonus(id, staffreversebonus); // Huh, again?
3528 relative = victim->coords - oldcoords;
3530 Normalise(&relative);
3531 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3532 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3534 victim->jointVel(abdomen) += relative * damagemult * 200;
3536 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3539 if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3545 Normalise(&relative);
3547 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3548 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3550 victim->jointVel(lefthand) *= .1;
3551 victim->jointVel(leftwrist) *= .2;
3552 victim->jointVel(leftelbow) *= .5;
3553 victim->jointVel(leftshoulder) *= .7;
3554 victim->jointVel(righthand) *= .1;
3555 victim->jointVel(rightwrist) *= .2;
3556 victim->jointVel(rightelbow) *= .5;
3557 victim->jointVel(rightshoulder) *= .7;
3559 victim->Puff(abdomen);
3560 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3562 award_bonus(id, Reversal);
3566 if (weaponactive != -1 || creature == wolftype) {
3569 if (creature == rabbittype && weaponactive != -1) {
3570 if (weapons[weaponids[0]].getType() == staff) {
3575 if (weaponactive != -1) {
3576 victim->DoBloodBig(2 / victim->armorhigh, 225);
3577 emit_sound_at(knifeslicesound, victim->coords);
3578 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3579 weapons[weaponids[weaponactive]].bloody = 1;
3581 weapons[weaponids[weaponactive]].blooddrip += 3;
3583 if (weaponactive == -1 && creature == wolftype) {
3584 emit_sound_at(clawslicesound, victim->coords, 128.);
3586 victim->DoBloodBig(2 / victim->armorhigh, 175);
3591 if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3597 Normalise(&relative);
3599 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3600 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3602 victim->jointVel(lefthand) *= .1 - 1;
3603 victim->jointVel(leftwrist) *= .2 - 1;
3604 victim->jointVel(leftelbow) *= .5 - 1;
3605 victim->jointVel(leftshoulder) *= .7 - 1;
3606 victim->jointVel(righthand) *= .1 - 1;
3607 victim->jointVel(rightwrist) *= .2 - 1;
3608 victim->jointVel(rightelbow) *= .5 - 1;
3609 victim->jointVel(rightshoulder) *= .7 - 1;
3611 award_bonus(id, swordreversebonus);
3614 if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3623 if (!Tutorial::active) {
3624 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3628 relative = victim->coords - oldcoords;
3630 Normalise(&relative);
3631 relative = DoRotation(relative, 0, -90, 0);
3632 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3633 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3635 victim->jointVel(abdomen) += relative * damagemult * 200;
3636 victim->Puff(abdomen);
3637 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3639 award_bonus(id, Reversal);
3642 if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3645 victim->skeleton.spinny = 0;
3647 relative = facing * -1;
3649 Normalise(&relative);
3650 if (victim->id == 0) {
3653 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3654 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3656 victim->damage = victim->damagetolerance;
3657 victim->permanentdamage = victim->damagetolerance - 1;
3660 if (weaponactive != -1 || creature == wolftype) {
3663 if (creature == rabbittype && weaponactive != -1) {
3664 if (weapons[weaponids[0]].getType() == staff) {
3669 if (weaponactive != -1) {
3670 victim->DoBloodBig(200, 225);
3671 emit_sound_at(knifeslicesound, victim->coords);
3673 weapons[weaponids[weaponactive]].bloody = 2;
3675 weapons[weaponids[weaponactive]].blooddrip += 5;
3678 if (creature == wolftype && weaponactive == -1) {
3679 emit_sound_at(clawslicesound, victim->coords, 128.);
3681 victim->DoBloodBig(2, 175);
3684 award_bonus(id, spinecrusher);
3687 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3688 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3690 if (animTarget == knifefollowanim) {
3691 victim->DoBloodBig(200, 210);
3693 if (animTarget == knifesneakattackanim) {
3694 XYZ footvel, footpoint;
3696 footpoint = weapons[weaponids[0]].tippoint;
3698 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3700 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3701 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3702 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3703 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3704 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3705 victim->DoBloodBig(200, 195);
3706 award_bonus(id, tracheotomy);
3708 if (animTarget == knifefollowanim) {
3709 award_bonus(id, Stabbonus);
3710 XYZ footvel, footpoint;
3712 footpoint = weapons[weaponids[0]].tippoint;
3714 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3716 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3717 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3718 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3719 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3720 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3722 victim->bloodloss += 10000;
3723 victim->velocity = 0;
3724 emit_sound_at(fleshstabsound, victim->coords);
3726 weapons[weaponids[weaponactive]].bloody = 2;
3728 weapons[weaponids[weaponactive]].blooddrip += 5;
3732 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3734 victim->velocity = 0;
3735 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3736 victim->skeleton.joints[i].velocity = 0;
3738 if (animTarget == knifefollowanim) {
3740 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3741 victim->skeleton.joints[i].velocity = 0;
3744 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3745 emit_sound_at(fleshstabremovesound, victim->coords);
3747 weapons[weaponids[weaponactive]].bloody = 2;
3749 weapons[weaponids[weaponactive]].blooddrip += 5;
3751 XYZ footvel, footpoint;
3753 footpoint = weapons[weaponids[0]].tippoint;
3755 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3757 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3758 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3759 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3760 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3761 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3765 if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3766 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3767 award_bonus(id, backstab);
3771 XYZ footvel, footpoint;
3773 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3775 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3777 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3778 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3779 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3780 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3781 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3782 victim->DoBloodBig(200, 180);
3783 victim->DoBloodBig(200, 215);
3784 victim->bloodloss += 10000;
3785 victim->velocity = 0;
3786 emit_sound_at(fleshstabsound, victim->coords);
3788 weapons[weaponids[weaponactive]].bloody = 2;
3790 weapons[weaponids[weaponactive]].blooddrip += 5;
3794 if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3796 victim->velocity = 0;
3797 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3798 victim->skeleton.joints[i].velocity = 0;
3800 if (weaponactive != -1) {
3801 emit_sound_at(fleshstabremovesound, victim->coords);
3803 weapons[weaponids[weaponactive]].bloody = 2;
3805 weapons[weaponids[weaponactive]].blooddrip += 5;
3807 XYZ footvel, footpoint;
3809 footpoint = weapons[weaponids[0]].tippoint;
3811 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3813 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3814 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3815 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3816 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3817 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3821 if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3830 if (weaponactive == -1) {
3831 if (!Tutorial::active) {
3832 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3837 if (weaponactive != -1 || creature == wolftype) {
3840 if (creature == rabbittype && weaponactive != -1) {
3841 if (weapons[weaponids[0]].getType() == staff) {
3846 if (weaponactive != -1) {
3847 victim->DoBloodBig(2 / victim->armorhead, 225);
3848 emit_sound_at(knifeslicesound, victim->coords);
3849 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3850 weapons[weaponids[weaponactive]].bloody = 1;
3852 weapons[weaponids[weaponactive]].blooddrip += 3;
3854 if (weaponactive == -1 && creature == wolftype) {
3855 emit_sound_at(clawslicesound, victim->coords, 128.);
3857 victim->DoBloodBig(2 / victim->armorhead, 175);
3861 award_bonus(id, Reversal);
3866 relative = facing * -1;
3868 Normalise(&relative);
3869 relative = DoRotation(relative, 0, 90, 0);
3871 Normalise(&relative);
3872 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3873 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3875 victim->jointVel(head) += relative * damagemult * 200;
3876 if (victim->damage < victim->damagetolerance - 100) {
3877 victim->velocity = relative * 200;
3879 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3880 victim->velocity = 0;
3883 if (animTarget == sweepreversalanim && ((Animation::animations[animTarget].frames[frameCurrent].label == 9 && victim->damage < victim->damagetolerance) || (Animation::animations[animTarget].frames[frameCurrent].label == 7 && victim->damage > victim->damagetolerance))) {
3887 relative = facing * -1;
3889 Normalise(&relative);
3890 relative = DoRotation(relative, 0, 90, 0);
3892 Normalise(&relative);
3893 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3894 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3896 victim->jointVel(head) += relative * damagemult * 200;
3899 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim)) {
3900 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3901 award_bonus(id, reverseko);
3907 if (frameTarget > int(Animation::animations[animCurrent].frames.size()) - 1) {
3910 animTarget = getIdle();
3911 FootLand(leftfoot, 1);
3912 FootLand(rightfoot, 1);
3914 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3915 animTarget = rollanim;
3917 emit_sound_at(movewhooshsound, coords, 128.);
3919 if (animCurrent == staggerbackhighanim) {
3920 animTarget = getIdle();
3922 if (animCurrent == staggerbackhardanim) {
3923 animTarget = getIdle();
3925 if (animCurrent == removeknifeanim) {
3926 animTarget = getIdle();
3928 if (animCurrent == crouchremoveknifeanim) {
3929 animTarget = getCrouch();
3931 if (animCurrent == backhandspringanim) {
3932 animTarget = getIdle();
3934 if (animCurrent == dodgebackanim) {
3935 animTarget = getIdle();
3937 if (animCurrent == drawleftanim) {
3938 animTarget = getIdle();
3940 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3941 animTarget = getIdle();
3942 if (animCurrent == crouchdrawrightanim) {
3943 animTarget = getCrouch();
3945 if (weaponactive == -1) {
3947 } else if (weaponactive == 0) {
3949 if (num_weapons == 2) {
3951 buffer = weaponids[0];
3952 weaponids[0] = weaponids[1];
3953 weaponids[1] = buffer;
3957 if (weaponactive == -1) {
3958 emit_sound_at(knifesheathesound, coords, 128.);
3960 if (weaponactive != -1) {
3961 emit_sound_at(knifedrawsound, coords, 128.);
3964 if (animCurrent == rollanim) {
3965 animTarget = getCrouch();
3966 FootLand(leftfoot, 1);
3967 FootLand(rightfoot, 1);
3970 if (animTarget == walljumprightkickanim) {
3973 if (animTarget == walljumpleftkickanim) {
3976 animTarget = jumpdownanim;
3978 if (animCurrent == climbanim) {
3979 animTarget = getCrouch();
3981 coords += facing * .1;
3982 if (!isnormal(coords.x)) {
3993 if (animTarget == rabbitkickreversalanim) {
3994 animTarget = getCrouch();
3997 if (animTarget == jumpreversalanim) {
3998 animTarget = getCrouch();
4001 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
4002 if (attackkeydown && animTarget != walljumpfrontanim) {
4004 float closestdist = -1;
4006 if (Person::players.size() > 1) {
4007 for (unsigned i = 0; i < Person::players.size(); i++) {
4008 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4009 distance = distsq(&Person::players[i]->coords, &coords);
4010 if (closestdist == -1 || distance < closestdist) {
4011 closestdist = distance;
4017 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4018 victim = Person::players[closest];
4019 animTarget = walljumprightkickanim;
4021 XYZ rotatetarget = victim->coords - coords;
4022 Normalise(&rotatetarget);
4023 yaw = -asin(0 - rotatetarget.x);
4025 if (rotatetarget.z < 0) {
4028 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4029 velocity = (victim->coords - coords) * 4;
4034 if (animTarget == walljumpbackanim) {
4035 animTarget = backflipanim;
4037 velocity = facing * -8;
4040 resume_stream(whooshsound);
4043 if (animTarget == walljumprightanim) {
4044 animTarget = rightflipanim;
4048 velocity = DoRotation(facing, 0, 30, 0) * -8;
4051 if (animTarget == walljumpfrontanim) {
4052 animTarget = frontflipanim;
4056 velocity = facing * 8;
4060 resume_stream(whooshsound);
4063 if (animTarget == walljumpleftanim) {
4064 if (attackkeydown) {
4066 float closestdist = -1;
4068 if (Person::players.size() > 1) {
4069 for (unsigned i = 0; i < Person::players.size(); i++) {
4070 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4071 distance = distsq(&Person::players[i]->coords, &coords);
4072 if (closestdist == -1 || distance < closestdist) {
4073 closestdist = distance;
4079 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4080 victim = Person::players[closest];
4081 animTarget = walljumpleftkickanim;
4083 XYZ rotatetarget = victim->coords - coords;
4084 Normalise(&rotatetarget);
4085 yaw = -asin(0 - rotatetarget.x);
4087 if (rotatetarget.z < 0) {
4090 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4091 velocity = (victim->coords - coords) * 4;
4096 if (animTarget != walljumpleftkickanim) {
4097 animTarget = leftflipanim;
4101 velocity = DoRotation(facing, 0, -30, 0) * -8;
4105 resume_stream(whooshsound);
4108 if (animTarget == sneakattackanim) {
4109 animCurrent = getCrouch();
4110 animTarget = getCrouch();
4117 transspeed = 1000000;
4118 targetheadyaw += 180;
4119 coords -= facing * .7;
4121 coords.y = terrain.getHeight(coords.x, coords.z);
4126 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
4127 animTarget = getIdle();
4130 coords.y = terrain.getHeight(coords.x, coords.z);
4135 if (animCurrent == knifefollowanim) {
4136 animTarget = getIdle();
4139 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
4140 float ycoords = oldcoords.y;
4141 animTarget = getStop();
4146 transspeed = 1000000;
4147 targetheadyaw += 180;
4148 if (!isnormal(coords.x)) {
4151 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim) {
4152 oldcoords = coords + facing * .5;
4153 } else if (animCurrent == sweepreversalanim) {
4154 oldcoords = coords + facing * 1.1;
4155 } else if (animCurrent == upunchreversalanim) {
4156 oldcoords = coords + facing * 1.5;
4159 targetheadyaw += 180;
4162 } else if (animCurrent == knifeslashreversalanim) {
4163 oldcoords = coords + facing * .5;
4166 targetheadyaw += 90;
4169 } else if (animCurrent == staffspinhitreversalanim) {
4172 targetheadyaw += 180;
4177 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
4179 oldcoords.y = ycoords;
4181 currentoffset = coords - oldcoords;
4187 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4192 if (Animation::animations[animTarget].attack == reversed) {
4194 if (animTarget == sweepreversedanim) {
4197 animTarget = backhandspringanim;
4199 emit_sound_at(landsound, coords, 128);
4201 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4202 animTarget = rollanim;
4205 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4206 coords.y = oldcoords.y;
4208 if (animCurrent == knifeslashreversedanim) {
4209 animTarget = rollanim;
4214 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4215 coords.y = oldcoords.y;
4219 animTarget = jumpdownanim;
4222 animTarget = getIdle();
4224 if (wasLandhard()) {
4225 animTarget = getIdle();
4227 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4228 animTarget = getIdle();
4230 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4231 coords.y = oldcoords.y;
4232 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4233 targetoffset.y = coords.y;
4235 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4237 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4238 currentoffset.y -= (coords.y - targetoffset.y);
4239 coords.y = targetoffset.y;
4241 normalsupdatedelay = 0;
4243 if (animCurrent == upunchanim) {
4244 animTarget = getStop();
4245 normalsupdatedelay = 0;
4248 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4252 if (num_weapons > 0) {
4253 if (weapons[0].getType() == staff) {
4262 rabbitkickragdoll = 1;
4264 if (animCurrent == rabbitkickreversedanim) {
4270 skeleton.spinny = 0;
4271 SolidHitBonus(!id); // FIXME: tricky id
4275 animTarget = rollanim;
4278 pause_sound(whooshsound);
4283 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4287 skeleton.spinny = 0;
4289 if (animCurrent == jumpreversedanim) {
4295 skeleton.spinny = 0;
4296 SolidHitBonus(!id); // FIXME: tricky id
4300 animTarget = rollanim;
4301 coords += facing * 2;
4303 pause_sound(whooshsound);
4309 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) {
4310 animTarget = getupfromfrontanim;
4312 } else if (Animation::animations[animCurrent].attack == normalattack) {
4313 animTarget = getIdle();
4316 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4317 animTarget = blockhighleftstrikeanim;
4319 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4320 animTarget = getIdle();
4323 if (animCurrent == spinkickanim && victim->skeleton.free) {
4324 if (creature == rabbittype) {
4325 animTarget = fightidleanim;
4331 if (isIdle() && !wasIdle()) {
4332 normalsupdatedelay = 0;
4335 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4336 animTarget = jumpdownanim;
4339 if (!skeleton.free) {
4341 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4342 if (!isRun() || !wasRun()) {
4343 if (targetFrame().speed > currentFrame().speed) {
4344 target += multiplier * targetFrame().speed * speed * 2;
4346 if (targetFrame().speed <= currentFrame().speed) {
4347 target += multiplier * currentFrame().speed * speed * 2;
4350 if (isRun() && wasRun()) {
4352 tempspeed = velspeed;
4353 if (tempspeed < 10 * speedmult) {
4354 tempspeed = 10 * speedmult;
4356 /* FIXME - mixed of target and current here, is that intended? */
4357 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4359 } else if (transspeed) {
4360 target += multiplier * transspeed * speed * 2;
4362 if (!isRun() || !wasRun()) {
4363 if (targetFrame().speed > currentFrame().speed) {
4364 target += multiplier * targetFrame().speed * 2;
4366 if (targetFrame().speed <= currentFrame().speed) {
4367 target += multiplier * currentFrame().speed * 2;
4372 if (animCurrent != animTarget) {
4373 target = (target + oldtarget) / 2;
4377 frameCurrent = frameTarget;
4381 rot = targetrot * target;
4382 yaw += rot - oldrot;
4388 if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
4389 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4391 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4393 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4394 skeleton.joints[i].position = currentFrame().joints[i].position;
4397 skeleton.FindForwards();
4399 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4400 if (skeleton.muscles[i].visible) {
4401 skeleton.FindRotationMuscle(i, animTarget);
4404 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4405 if (skeleton.muscles[i].visible) {
4406 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4407 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4409 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4410 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4412 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4413 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4419 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4420 skeleton.joints[i].position = targetFrame().joints[i].position;
4423 skeleton.FindForwards();
4425 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4426 if (skeleton.muscles[i].visible) {
4427 skeleton.FindRotationMuscle(i, animTarget);
4430 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4431 if (skeleton.muscles[i].visible) {
4432 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4433 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4435 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4436 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4438 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4439 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4441 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) {
4442 skeleton.muscles[i].newrotate3 -= 360;
4444 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) {
4445 skeleton.muscles[i].newrotate3 += 360;
4447 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) {
4448 skeleton.muscles[i].newrotate2 -= 360;
4450 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) {
4451 skeleton.muscles[i].newrotate2 += 360;
4453 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) {
4454 skeleton.muscles[i].newrotate1 -= 360;
4456 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) {
4457 skeleton.muscles[i].newrotate1 += 360;
4463 oldanimCurrent = animCurrent;
4464 oldanimTarget = animTarget;
4465 oldframeTarget = frameTarget;
4466 oldframeCurrent = frameCurrent;
4468 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4469 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target - skeleton.joints[i].position) / multiplier;
4470 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target;
4472 offset = currentoffset * (1 - target) + targetoffset * target;
4473 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4474 if (skeleton.muscles[i].visible) {
4475 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * target;
4476 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * target;
4477 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * target;
4482 if (isLanding() && landhard) {
4486 animTarget = getLandhard();
4499 void Person::DoStuff()
4501 static XYZ terrainnormal;
4502 static XYZ flatfacing;
4503 static XYZ flatvelocity;
4504 static float flatvelspeed;
4505 static int bloodsize;
4506 static int startx, starty, endx, endy;
4507 static GLubyte color;
4508 static XYZ bloodvel;
4510 onfiredelay -= multiplier;
4511 if (onfiredelay < 0 && onfire) {
4512 if (Random() % 2 == 0) {
4518 crouchkeydowntime += multiplier;
4519 if (!crouchkeydown) {
4520 crouchkeydowntime = 0;
4522 jumpkeydowntime += multiplier;
4523 if (!jumpkeydown && skeleton.free) {
4524 jumpkeydowntime = 0;
4527 if (hostile || damage > 0 || bloodloss > 0) {
4531 if (isIdle() || isRun()) {
4535 if (num_weapons == 1 && weaponactive != -1) {
4540 blooddimamount -= multiplier * .3;
4542 speechdelay -= multiplier;
4543 texupdatedelay -= multiplier;
4544 interestdelay -= multiplier;
4545 flamedelay -= multiplier;
4546 parriedrecently -= multiplier;
4548 victim = this->shared_from_this();
4553 speed = 1.1 * speedmult;
4555 speed = 1.0 * speedmult;
4557 if (!skeleton.free) {
4558 rabbitkickragdoll = 0;
4563 if (id != 0 && (creature == rabbittype || difficulty != 2)) {
4566 if (id != 0 && creature == wolftype && difficulty == 2) {
4568 if (aitype != passivetype) {
4570 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) {
4577 if (animTarget == wolfrunninganim && !superruntoggle) {
4578 animTarget = getRun();
4582 if (weaponactive == -1 && num_weapons > 0) {
4583 if (weapons[weaponids[0]].getType() == staff) {
4589 burnt += multiplier;
4594 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4596 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4603 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
4604 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4608 while (flamedelay < 0 && onfire) {
4610 int howmany = fabs(Random() % (skeleton.joints.size()));
4611 if (skeleton.free) {
4612 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4613 flatfacing = skeleton.joints[howmany].position * scale + coords;
4615 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4616 flatvelocity = (coords - oldcoords) / multiplier / 2;
4618 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4621 while (flamedelay < 0 && !onfire && Tutorial::active && id != 0) {
4623 int howmany = fabs(Random() % (skeleton.joints.size()));
4624 if (skeleton.free) {
4625 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4626 flatfacing = skeleton.joints[howmany].position * scale + coords;
4628 flatvelocity = (coords - oldcoords) / multiplier / 2;
4629 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4631 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4635 bleeding -= multiplier * .3;
4636 if (bloodtoggle == 2) {
4637 skeleton.drawmodel.textureptr.bind();
4638 if ((bleeding <= 0) && (detail != 2)) {
4644 if (neckspurtamount > 0) {
4645 neckspurtamount -= multiplier;
4646 neckspurtdelay -= multiplier * 3;
4647 neckspurtparticledelay -= multiplier * 3;
4648 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4651 if (skeleton.free) {
4652 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4653 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4654 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4656 bloodvel.z = 5 * neckspurtamount;
4657 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4658 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4659 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4661 neckspurtparticledelay = .05;
4663 if (neckspurtdelay < 0) {
4668 if (deathbleeding > 0 && dead != 2) {
4669 if (deathbleeding < 5) {
4670 bleeddelay -= deathbleeding * multiplier / 4;
4672 bleeddelay -= 5 * multiplier / 4;
4674 if (bleeddelay < 0 && bloodtoggle) {
4679 if (skeleton.free) {
4680 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4681 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4683 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4684 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4688 bloodloss += deathbleeding * multiplier * 80;
4689 deathbleeding -= multiplier * 1.6;
4690 if (deathbleeding < 0) {
4693 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4694 if (weaponactive != -1) {
4695 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4696 weapons[weaponids[0]].velocity.x += .01;
4699 weaponids[0] = weaponids[num_weapons];
4700 if (weaponstuck == num_weapons) {
4705 for (unsigned i = 0; i < Person::players.size(); i++) {
4706 Person::players[i]->wentforweapon = 0;
4714 if (!dead && creature == wolftype) {
4715 award_bonus(0, Wolfbonus);
4718 if (animTarget == knifefollowedanim && !skeleton.free) {
4719 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4720 skeleton.joints[i].velocity = 0;
4721 skeleton.joints[i].velocity.y = -2;
4724 if (id != 0 && unconscioustime > .1) {
4732 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4733 texupdatedelay = .12;
4735 bloodsize = 5 - realtexdetail;
4739 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4740 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4741 endx = startx + bloodsize;
4742 endy = starty + bloodsize;
4752 if (endx > skeleton.skinsize - 1) {
4753 endx = skeleton.skinsize - 1;
4756 if (endy > skeleton.skinsize - 1) {
4757 endy = skeleton.skinsize - 1;
4760 if (endx < startx) {
4763 if (endy < starty) {
4767 for (int i = startx; i < endx; i++) {
4768 for (int j = starty; j < endy; j++) {
4769 if (Random() % 2 == 0) {
4770 color = Random() % 85 + 170;
4771 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2) {
4772 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4774 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4775 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4780 skeleton.drawmodel.textureptr.bind();
4784 if (skeleton.free) {
4785 bleedx += 4 * direction / realtexdetail;
4787 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4789 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4792 bleedy -= 4 / realtexdetail;
4794 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4796 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4801 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4802 righthandmorphness = targetrighthandmorphness;
4803 righthandmorphstart = righthandmorphend;
4804 } else if (righthandmorphness > targetrighthandmorphness) {
4805 righthandmorphness -= multiplier * 4;
4806 } else if (righthandmorphness < targetrighthandmorphness) {
4807 righthandmorphness += multiplier * 4;
4810 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4811 lefthandmorphness = targetlefthandmorphness;
4812 lefthandmorphstart = lefthandmorphend;
4813 } else if (lefthandmorphness > targetlefthandmorphness) {
4814 lefthandmorphness -= multiplier * 4;
4815 } else if (lefthandmorphness < targetlefthandmorphness) {
4816 lefthandmorphness += multiplier * 4;
4819 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4820 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4821 tailmorphness = targettailmorphness;
4822 tailmorphstart = tailmorphend;
4823 } else if (tailmorphness > targettailmorphness) {
4824 tailmorphness -= multiplier * 10;
4825 } else if (tailmorphness < targettailmorphness) {
4826 tailmorphness += multiplier * 10;
4830 if (creature == wolftype) {
4831 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4832 tailmorphness = targettailmorphness;
4833 tailmorphstart = tailmorphend;
4834 } else if (tailmorphness > targettailmorphness) {
4835 tailmorphness -= multiplier * 2;
4836 } else if (tailmorphness < targettailmorphness) {
4837 tailmorphness += multiplier * 2;
4841 if (headmorphend == 3 || headmorphstart == 3) {
4842 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4843 headmorphness = targetheadmorphness;
4844 headmorphstart = headmorphend;
4845 } else if (headmorphness > targetheadmorphness) {
4846 headmorphness -= multiplier * 7;
4847 } else if (headmorphness < targetheadmorphness) {
4848 headmorphness += multiplier * 7;
4850 } else if (headmorphend == 5 || headmorphstart == 5) {
4851 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4852 headmorphness = targetheadmorphness;
4853 headmorphstart = headmorphend;
4854 } else if (headmorphness > targetheadmorphness) {
4855 headmorphness -= multiplier * 10;
4856 } else if (headmorphness < targetheadmorphness) {
4857 headmorphness += multiplier * 10;
4860 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4861 headmorphness = targetheadmorphness;
4862 headmorphstart = headmorphend;
4863 } else if (headmorphness > targetheadmorphness) {
4864 headmorphness -= multiplier * 4;
4865 } else if (headmorphness < targetheadmorphness) {
4866 headmorphness += multiplier * 4;
4870 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4871 chestmorphness = targetchestmorphness;
4872 chestmorphstart = chestmorphend;
4873 } else if (chestmorphness > targetchestmorphness) {
4874 chestmorphness -= multiplier;
4875 } else if (chestmorphness < targetchestmorphness) {
4876 chestmorphness += multiplier;
4879 if (dead != 2 && howactive <= typesleeping) {
4880 if (chestmorphstart == 0 && chestmorphend == 0) {
4882 targetchestmorphness = 1;
4885 if (chestmorphstart != 0 && chestmorphend != 0) {
4887 targetchestmorphness = 1;
4889 if (environment == snowyenvironment) {
4892 if (skeleton.free) {
4893 footvel = skeleton.specialforward[0] * -1;
4894 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4896 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4897 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4899 if (animTarget == sleepanim) {
4900 footvel = DoRotation(footvel, 0, 90, 0);
4902 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4906 if (!dead && howactive < typesleeping) {
4907 blinkdelay -= multiplier * 2;
4908 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4910 targetheadmorphness = 1;
4912 blinkdelay = (float)(abs(Random() % 40)) / 5;
4914 if (headmorphstart == 3 && headmorphend == 3) {
4916 targetheadmorphness = 1;
4921 twitchdelay -= multiplier * 1.5;
4922 if (animTarget != hurtidleanim) {
4923 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4925 targetheadmorphness = 1;
4927 twitchdelay = (float)(abs(Random() % 40)) / 5;
4929 if (headmorphstart == 5 && headmorphend == 5) {
4931 targetheadmorphness = 1;
4935 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4936 twitchdelay3 -= multiplier * 1;
4937 if (Random() % 2 == 0) {
4938 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4939 righthandmorphness = 0;
4940 targetrighthandmorphness = 1;
4941 righthandmorphend = 1;
4942 if (Random() % 2 == 0) {
4943 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4946 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4947 righthandmorphness = 0;
4948 targetrighthandmorphness = 1;
4949 righthandmorphend = 0;
4952 if (Random() % 2 == 0) {
4953 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4954 lefthandmorphness = 0;
4955 targetlefthandmorphness = 1;
4956 lefthandmorphend = 1;
4957 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4959 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4960 lefthandmorphness = 0;
4961 targetlefthandmorphness = 1;
4962 lefthandmorphend = 0;
4968 if (creature == rabbittype) {
4969 if (howactive < typesleeping) {
4970 twitchdelay2 -= multiplier * 1.5;
4972 twitchdelay2 -= multiplier * 0.5;
4974 if (howactive <= typesleeping) {
4975 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4977 targettailmorphness = 1;
4979 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4981 if (tailmorphstart == 1 && tailmorphend == 1) {
4983 targettailmorphness = 1;
4986 if (tailmorphstart == 2 && tailmorphend == 2) {
4988 targettailmorphness = 1;
4995 if (creature == wolftype) {
4996 twitchdelay2 -= multiplier * 1.5;
4997 if (tailmorphend != 0) {
4998 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
5000 targettailmorphness = 1;
5005 if (tailmorphend != 5) {
5006 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
5008 targettailmorphness = 1;
5013 if (twitchdelay2 <= 0) {
5014 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
5016 targettailmorphness = 1;
5019 if (tailmorphstart == 1 && tailmorphend == 1) {
5021 targettailmorphness = 1;
5024 if (tailmorphstart == 2 && tailmorphend == 2) {
5026 targettailmorphness = 1;
5029 if (tailmorphstart == 3 && tailmorphend == 3) {
5031 targettailmorphness = 1;
5034 if (tailmorphstart == 4 && tailmorphend == 4) {
5036 targettailmorphness = 1;
5043 unconscioustime = 0;
5046 if (dead == 1 || howactive == typesleeping) {
5047 unconscioustime += multiplier;
5048 //If unconscious, close eyes and mouth
5049 if (righthandmorphend != 0) {
5050 righthandmorphness = 0;
5052 righthandmorphend = 0;
5053 targetrighthandmorphness = 1;
5055 if (lefthandmorphend != 0) {
5056 lefthandmorphness = 0;
5058 lefthandmorphend = 0;
5059 targetlefthandmorphness = 1;
5061 if (headmorphend != 3 && headmorphend != 5) {
5065 targetheadmorphness = 1;
5068 if (howactive > typesleeping) {
5071 if (bloodtoggle && !bled) {
5072 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5073 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5074 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5075 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5079 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5085 if (dead == 2 || howactive > typesleeping) {
5086 //If dead, open mouth and hands
5087 if (righthandmorphend != 0) {
5088 righthandmorphness = 0;
5090 righthandmorphend = 0;
5091 targetrighthandmorphness = 1;
5093 if (lefthandmorphend != 0) {
5094 lefthandmorphness = 0;
5096 lefthandmorphend = 0;
5097 targetlefthandmorphness = 1;
5099 if (headmorphend != 2) {
5103 targetheadmorphness = 1;
5106 if (stunned > 0 && !dead && headmorphend != 2) {
5107 if (headmorphend != 4) {
5111 targetheadmorphness = 1;
5114 if (damage > damagetolerance && !dead) {
5117 unconscioustime = 0;
5119 if (creature == wolftype) {
5120 award_bonus(0, Wolfbonus);
5125 if (weaponactive != -1) {
5126 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5127 weapons[weaponids[0]].velocity.x += .01;
5130 weaponids[0] = weaponids[num_weapons];
5131 if (weaponstuck == num_weapons) {
5136 for (unsigned i = 0; i < Person::players.size(); i++) {
5137 Person::players[i]->wentforweapon = 0;
5141 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
5150 damage -= multiplier * 13;
5151 permanentdamage -= multiplier * 4;
5152 if (isIdle() || isCrouch()) {
5153 permanentdamage -= multiplier * 4;
5159 if (permanentdamage < 0) {
5160 permanentdamage = 0;
5162 if (superpermanentdamage < 0) {
5163 superpermanentdamage = 0;
5165 if (permanentdamage < superpermanentdamage) {
5166 permanentdamage = superpermanentdamage;
5168 if (damage < permanentdamage) {
5169 damage = permanentdamage;
5171 if (dead == 1 && damage < damagetolerance) {
5175 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5176 skeleton.joints[i].velocity = 0;
5179 if (permanentdamage > damagetolerance && dead != 2) {
5182 if (weaponactive != -1) {
5183 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5184 weapons[weaponids[0]].velocity.x += .01;
5187 weaponids[0] = weaponids[num_weapons];
5188 if (weaponstuck == num_weapons) {
5193 for (unsigned i = 0; i < Person::players.size(); i++) {
5194 Person::players[i]->wentforweapon = 0;
5200 if (!dead && creature == wolftype) {
5201 award_bonus(0, Wolfbonus);
5204 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance) {
5205 award_bonus(id, touchofdeath);
5207 if (id != 0 && unconscioustime > .1) {
5215 emit_sound_at(breaksound, coords);
5218 if (skeleton.free == 1) {
5220 pause_sound(whooshsound);
5224 //If knocked over, open hands and close mouth
5225 if (righthandmorphend != 0) {
5226 righthandmorphness = 0;
5228 righthandmorphend = 0;
5229 targetrighthandmorphness = 1;
5231 if (lefthandmorphend != 0) {
5232 lefthandmorphness = 0;
5234 lefthandmorphend = 0;
5235 targetlefthandmorphness = 1;
5237 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
5238 if (headmorphend != 0) {
5242 targetheadmorphness = 1;
5246 skeleton.DoGravity(&scale);
5248 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
5249 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1)) {
5250 award_bonus(id, deepimpact);
5252 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5256 if (!skeleton.joints.empty()) {
5257 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5258 average += skeleton.joints[j].position;
5260 average /= skeleton.joints.size();
5261 coords += average * scale;
5262 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5263 skeleton.joints[j].position -= average;
5265 average /= multiplier;
5269 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5270 velocity += skeleton.joints[i].velocity * scale;
5272 velocity /= skeleton.joints.size();
5274 if (!isnormal(velocity.x) && velocity.x) {
5278 if (findLength(&average) < 10 && dead && skeleton.free) {
5279 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5280 if (skeleton.longdead > 2000) {
5281 if (skeleton.longdead > 6000) {
5283 pause_sound(whooshsound);
5289 if (dead == 2 && bloodloss < damagetolerance) {
5291 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5293 if (bloodtoggle && !bled) {
5294 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5295 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5296 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5297 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5298 float size = .2 * 1.2;
5301 Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5306 if (dead == 2 && bloodloss >= damagetolerance) {
5308 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5309 if (bleeding <= 0) {
5312 if (bloodtoggle && !bled) {
5313 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5314 for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5315 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5316 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5320 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5328 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5329 bool canrecover = 1;
5330 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5331 startpoint = coords;
5334 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1) {
5337 if (velocity.y < -30) {
5340 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5341 if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) {
5342 colviewer = startpoint;
5343 coltarget = endpoint;
5344 if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1) {
5354 terrainnormal = jointPos(groin) - jointPos(abdomen);
5355 if (joint(groin).locked && joint(abdomen).locked) {
5356 terrainnormal = jointPos(groin) - jointPos(abdomen);
5357 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5359 if (joint(abdomen).locked && joint(neck).locked) {
5360 terrainnormal = jointPos(abdomen) - jointPos(neck);
5361 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5363 if (joint(groin).locked && joint(neck).locked) {
5364 terrainnormal = jointPos(groin) - jointPos(neck);
5365 middle = (jointPos(groin) + jointPos(neck)) / 2;
5367 Normalise(&terrainnormal);
5369 targetyaw = -asin(0 - terrainnormal.x);
5370 targetyaw *= 360 / 6.28;
5371 if (terrainnormal.z < 0) {
5372 targetyaw = 180 - targetyaw;
5377 animTarget = flipanim;
5378 crouchtogglekeydown = 1;
5383 animCurrent = tempanim;
5387 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5388 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5389 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5394 if (findLength(&average) < 10 && !dead && skeleton.free) {
5395 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5396 if (skeleton.longdead > (damage + 500) * 1.5) {
5398 pause_sound(whooshsound);
5405 terrainnormal = jointPos(groin) - jointPos(abdomen);
5406 if (joint(groin).locked && joint(abdomen).locked) {
5407 terrainnormal = jointPos(groin) - jointPos(abdomen);
5408 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5410 if (joint(abdomen).locked && joint(neck).locked) {
5411 terrainnormal = jointPos(abdomen) - jointPos(neck);
5412 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5414 if (joint(groin).locked && joint(neck).locked) {
5415 terrainnormal = jointPos(groin) - jointPos(neck);
5416 middle = (jointPos(groin) + jointPos(neck)) / 2;
5418 Normalise(&terrainnormal);
5420 targetyaw = -asin(0 - terrainnormal.x);
5421 targetyaw *= 360 / 6.28;
5422 if (terrainnormal.z < 0) {
5423 targetyaw = 180 - targetyaw;
5427 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5429 if (skeleton.forward.y < 0) {
5430 animTarget = getupfrombackanim;
5434 if (skeleton.forward.y > -.3) {
5435 animTarget = getupfromfrontanim;
5443 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5444 animTarget = rollanim;
5445 targetyaw = lookyaw;
5449 if (forwardkeydown) {
5458 if (forwardkeydown) {
5466 if (!leftkeydown && !rightkeydown) {
5474 if (abs(targettilt2) > 50) {
5477 animCurrent = tempanim;
5480 tilt2 = targettilt2;
5482 if (middle.y > 0 && animTarget != rollanim) {
5483 targetoffset.y = middle.y + 1;
5486 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5487 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5488 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5495 if (num_weapons > 0) {
5496 if (weapons[0].getType() == staff) {
5500 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5501 if (velocity.y > -30) {
5503 tempvelocity = velocity;
5504 Normalise(&tempvelocity);
5505 targetyaw = -asin(0 - tempvelocity.x);
5506 targetyaw *= 360 / 6.28;
5507 if (velocity.z < 0) {
5508 targetyaw = 180 - targetyaw;
5513 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5514 animTarget = rollanim;
5517 animTarget = backhandspringanim;
5523 emit_sound_at(movewhooshsound, coords, 128.);
5525 animCurrent = animTarget;
5526 frameCurrent = frameTarget - 1;
5538 if (skeleton.freefall == 0) {
5543 if (aitype != passivetype || skeleton.free == 1) {
5544 if (findLengthfast(&velocity) > .1) {
5545 for (unsigned int i = 0; i < Object::objects.size(); i++) {
5546 if (Object::objects[i]->type == firetype) {
5547 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) {
5549 if (!Object::objects[i]->onfire) {
5550 emit_sound_at(firestartsound, Object::objects[i]->position);
5552 Object::objects[i]->onfire = 1;
5555 if (Object::objects[i]->onfire) {
5561 if (Object::objects[i]->type == bushtype) {
5562 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) {
5564 if (!Object::objects[i]->onfire) {
5565 emit_sound_at(firestartsound, Object::objects[i]->position);
5567 Object::objects[i]->onfire = 1;
5571 if (Object::objects[i]->onfire) {
5575 if (Object::objects[i]->messedwith <= 0) {
5579 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5582 addEnvSound(coords, 4 * findLength(&velocity));
5586 if (environment == grassyenvironment) {
5587 howmany = findLength(&velocity) * 4;
5589 if (environment == snowyenvironment) {
5590 howmany = findLength(&velocity) * 2;
5593 if (environment != desertenvironment) {
5594 for (int j = 0; j < howmany; j++) {
5595 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5596 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5597 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5600 pos.x += float(abs(Random() % 100) - 50) / 200;
5601 pos.y += float(abs(Random() % 100) - 50) / 200;
5602 pos.z += float(abs(Random() % 100) - 50) / 200;
5603 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);
5604 Sprite::setLastSpriteSpecial(1);
5608 howmany = findLength(&velocity) * 4;
5610 if (environment == snowyenvironment) {
5611 for (int j = 0; j < howmany; j++) {
5612 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5613 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5614 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5617 pos.x += float(abs(Random() % 100) - 50) / 200;
5618 pos.y += float(abs(Random() % 100) - 50) / 200;
5619 pos.z += float(abs(Random() % 100) - 50) / 200;
5620 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5621 Sprite::setLastSpriteSpecial(2);
5626 Object::objects[i]->rotx += velocity.x * multiplier * 6;
5627 Object::objects[i]->roty += velocity.z * multiplier * 6;
5628 Object::objects[i]->messedwith = .5;
5632 if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) {
5633 if (Object::objects[i]->pitch == 0) {
5636 tempcoord = coords - Object::objects[i]->position;
5637 tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0);
5638 tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0);
5639 tempcoord += Object::objects[i]->position;
5641 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) {
5642 if (Object::objects[i]->messedwith <= 0) {
5646 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5649 addEnvSound(coords, 4 * findLength(&velocity));
5653 if (environment == grassyenvironment) {
5654 howmany = findLength(&velocity) * 4;
5656 if (environment == snowyenvironment) {
5657 howmany = findLength(&velocity) * 2;
5660 if (environment != desertenvironment) {
5661 for (int j = 0; j < howmany; j++) {
5662 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5663 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5664 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5666 pos += velocity * .1;
5668 pos.x += float(abs(Random() % 100) - 50) / 150;
5669 pos.y += float(abs(Random() % 100) - 50) / 150;
5670 pos.z += float(abs(Random() % 100) - 50) / 150;
5671 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);
5672 Sprite::setLastSpriteSpecial(1);
5676 howmany = findLength(&velocity) * 4;
5678 if (environment == snowyenvironment) {
5679 for (int j = 0; j < howmany; j++) {
5680 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5681 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5682 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5684 pos += velocity * .1;
5686 pos.x += float(abs(Random() % 100) - 50) / 150;
5687 pos.y += float(abs(Random() % 100) - 50) / 150;
5688 pos.z += float(abs(Random() % 100) - 50) / 150;
5689 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5690 Sprite::setLastSpriteSpecial(2);
5695 Object::objects[i]->messedwith = .5;
5702 if (!skeleton.free) {
5705 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype) {
5709 if (aitype != passivetype && victim->skeleton.free && !victim->dead) {
5713 if (Tutorial::active && id != 0) {
5716 if (play && aitype != playercontrolled) {
5717 int whichsound = -1;
5718 if (speechdelay <= 0) {
5719 unsigned int i = abs(Random() % 4);
5721 whichsound = PersonType::types[creature].soundsTalk[i];
5726 if (whichsound != -1) {
5727 emit_sound_at(whichsound, coords);
5731 if (animTarget == staggerbackhighanim) {
5734 if (animTarget == staggerbackhardanim) {
5737 staggerdelay -= multiplier;
5738 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
5741 if (velocity.y < -30 && animTarget == jumpdownanim) {
5744 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5745 animTarget = getIdle();
5749 weaponmissdelay -= multiplier;
5750 highreversaldelay -= multiplier;
5751 lowreversaldelay -= multiplier;
5752 lastcollide -= multiplier;
5753 skiddelay -= multiplier;
5754 if (!isnormal(velocity.x) && velocity.x) {
5757 if (!isnormal(targettilt) && targettilt) {
5760 if (!isnormal(targettilt2) && targettilt2) {
5763 if (!isnormal(targetyaw) && targetyaw) {
5767 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5768 //open hands and close mouth
5769 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5770 righthandmorphness = 0;
5771 righthandmorphend = 0;
5772 targetrighthandmorphness = 1;
5775 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5776 lefthandmorphness = 0;
5777 lefthandmorphend = 0;
5778 targetlefthandmorphness = 1;
5781 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5784 targetheadmorphness = 1;
5788 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) {
5789 //open hands and mouth
5790 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5791 righthandmorphness = 0;
5792 righthandmorphend = 0;
5793 targetrighthandmorphness = 1;
5796 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5797 lefthandmorphness = 0;
5798 lefthandmorphend = 0;
5799 targetlefthandmorphness = 1;
5802 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5805 targetheadmorphness = 1;
5809 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5810 //close hands and mouth
5811 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5812 righthandmorphness = 0;
5813 righthandmorphend = 1;
5814 targetrighthandmorphness = 1;
5817 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5818 lefthandmorphness = 0;
5819 lefthandmorphend = 1;
5820 targetlefthandmorphness = 1;
5823 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5826 targetheadmorphness = 1;
5830 if (animTarget == spinkickanim ||
5831 animTarget == staffspinhitreversalanim ||
5832 animTarget == staffspinhitreversedanim ||
5833 animTarget == staffhitreversalanim ||
5834 animTarget == staffhitreversedanim ||
5835 animTarget == hurtidleanim ||
5836 animTarget == winduppunchanim ||
5837 animTarget == swordslashreversalanim ||
5838 animTarget == swordslashreversedanim ||
5839 animTarget == knifeslashreversalanim ||
5840 animTarget == knifeslashreversedanim ||
5841 animTarget == knifethrowanim ||
5842 animTarget == knifefollowanim ||
5843 animTarget == knifefollowedanim ||
5844 animTarget == killanim ||
5845 animTarget == dropkickanim ||
5846 animTarget == upunchanim ||
5847 animTarget == knifeslashstartanim ||
5848 animTarget == swordslashanim ||
5849 animTarget == staffhitanim ||
5850 animTarget == staffspinhitanim ||
5851 animTarget == staffgroundsmashanim ||
5852 animTarget == spinkickreversalanim ||
5853 animTarget == sweepreversalanim ||
5854 animTarget == lowkickanim ||
5855 animTarget == sweepreversedanim ||
5856 animTarget == rabbitkickreversalanim ||
5857 animTarget == rabbitkickreversedanim ||
5858 animTarget == jumpreversalanim ||
5859 animTarget == jumpreversedanim) {
5860 //close hands and yell
5861 if (righthandmorphend != 1 &&
5862 righthandmorphness == targetrighthandmorphness) {
5863 righthandmorphness = 0;
5864 righthandmorphend = 1;
5865 targetrighthandmorphness = 1;
5868 if (lefthandmorphend != 1 &&
5869 lefthandmorphness == targetlefthandmorphness) {
5870 lefthandmorphness = 0;
5871 lefthandmorphend = 1;
5872 targetlefthandmorphness = 1;
5875 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5878 targetheadmorphness = 1;
5885 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5886 (victim->aitype != searchtype) && (aitype != passivetype) &&
5887 (aitype != searchtype) && (victim->id < Person::players.size())) {
5888 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5892 if (!dead && animTarget != hurtidleanim) {
5893 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5894 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5897 targetheadmorphness = 1;
5902 if (weaponactive != -1) {
5903 if (weapons[weaponids[weaponactive]].getType() != staff) {
5904 righthandmorphstart = 1;
5905 righthandmorphend = 1;
5907 if (weapons[weaponids[weaponactive]].getType() == staff) {
5908 righthandmorphstart = 2;
5909 righthandmorphend = 2;
5911 targetrighthandmorphness = 1;
5914 terrainnormal = terrain.getNormal(coords.x, coords.z);
5916 if (Animation::animations[animTarget].attack != reversal) {
5917 if (!isnormal(coords.x)) {
5926 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5927 facing = flatfacing;
5928 ReflectVector(&facing, terrainnormal);
5932 animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5934 targettilt2 = -facing.y * 20;
5940 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim) {
5943 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5944 flatvelocity = velocity;
5946 flatvelspeed = findLength(&flatvelocity);
5947 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5948 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5949 if (velocity.y < 0) {
5952 if (velocity.y < 0) {
5955 if (targettilt > 25) {
5958 if (targettilt < -25) {
5963 if (targettilt2 > 45) {
5966 if (targettilt2 < -45) {
5969 if (abs(tilt2 - targettilt2) < multiplier * 400) {
5970 tilt2 = targettilt2;
5971 } else if (tilt2 > targettilt2) {
5972 tilt2 -= multiplier * 400;
5973 } else if (tilt2 < targettilt2) {
5974 tilt2 += multiplier * 400;
5976 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5985 if (!isnormal(targettilt) && targettilt) {
5988 if (!isnormal(targettilt2) && targettilt2) {
5993 if (animTarget == rabbittackleanim) {
5994 velocity += facing * multiplier * speed * 700 * scale;
5995 velspeed = findLength(&velocity);
5996 if (velspeed > speed * 65 * scale) {
5997 velocity /= velspeed;
5998 velspeed = speed * 65 * scale;
5999 velocity *= velspeed;
6001 velocity.y += gravity * multiplier * 20;
6002 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6003 velspeed = findLength(&velocity);
6004 velocity = flatfacing * velspeed;
6006 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
6007 if (isRun() || animTarget == rabbitkickanim) {
6008 velocity += facing * multiplier * speed * 700 * scale;
6009 velspeed = findLength(&velocity);
6010 if (velspeed > speed * 45 * scale) {
6011 velocity /= velspeed;
6012 velspeed = speed * 45 * scale;
6013 velocity *= velspeed;
6015 velocity.y += gravity * multiplier * 20;
6016 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6017 velspeed = findLength(&velocity);
6018 if (velspeed < speed * 30 * scale) {
6019 velspeed = speed * 30 * scale;
6021 velocity = flatfacing * velspeed;
6023 } else if (isRun()) {
6024 velocity += facing * multiplier * speed * 700 * scale;
6025 velspeed = findLength(&velocity);
6026 if (creature == rabbittype) {
6027 if (velspeed > speed * 55 * scale) {
6028 velocity /= velspeed;
6029 velspeed = speed * 55 * scale;
6030 velocity *= velspeed;
6033 if (creature == wolftype) {
6034 if (velspeed > speed * 75 * scale) {
6035 velocity /= velspeed;
6036 velspeed = speed * 75 * scale;
6037 velocity *= velspeed;
6040 velocity.y += gravity * multiplier * 20;
6041 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6042 velspeed = findLength(&velocity);
6043 velocity = flatfacing * velspeed;
6046 if (animTarget == rollanim && targetFrame().label != 6) {
6047 velocity += facing * multiplier * speed * 700 * scale;
6048 velspeed = findLength(&velocity);
6049 if (velspeed > speed * 45 * scale) {
6050 velocity /= velspeed;
6051 velspeed = speed * 45 * scale;
6052 velocity *= velspeed;
6054 velocity.y += gravity * multiplier * 20;
6055 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6056 velspeed = findLength(&velocity);
6057 velocity = flatfacing * velspeed;
6060 if (animTarget == sneakanim || animTarget == walkanim) {
6061 velocity += facing * multiplier * speed * 700 * scale;
6062 velspeed = findLength(&velocity);
6063 if (velspeed > speed * 12 * scale) {
6064 velocity /= velspeed;
6065 velspeed = speed * 12 * scale;
6066 velocity *= velspeed;
6068 velocity.y += gravity * multiplier * 20;
6069 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6070 velspeed = findLength(&velocity);
6071 velocity = flatfacing * velspeed;
6074 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
6075 velocity += facing * multiplier * speed * 700 * scale;
6076 velspeed = findLength(&velocity);
6077 if (velspeed > speed * 2 * scale) {
6078 velocity /= velspeed;
6079 velspeed = speed * 2 * scale;
6080 velocity *= velspeed;
6082 velocity.y += gravity * multiplier * 20;
6083 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6084 velspeed = findLength(&velocity);
6085 velocity = flatfacing * velspeed;
6088 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
6089 velocity -= facing * multiplier * speed * 700 * scale;
6090 velspeed = findLength(&velocity);
6091 if (velspeed > speed * 2 * scale) {
6092 velocity /= velspeed;
6093 velspeed = speed * 2 * scale;
6094 velocity *= velspeed;
6096 velocity.y += gravity * multiplier * 20;
6097 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6098 velspeed = findLength(&velocity);
6099 velocity = flatfacing * velspeed * -1;
6102 if (animTarget == fightsidestep) {
6103 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
6104 velspeed = findLength(&velocity);
6105 if (velspeed > speed * 12 * scale) {
6106 velocity /= velspeed;
6107 velspeed = speed * 12 * scale;
6108 velocity *= velspeed;
6110 velocity.y += gravity * multiplier * 20;
6111 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6112 velspeed = findLength(&velocity);
6113 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
6116 if (animTarget == staggerbackhighanim) {
6117 coords -= facing * multiplier * speed * 16 * scale;
6120 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
6121 coords -= facing * multiplier * speed * 20 * scale;
6125 if (animTarget == backhandspringanim) {
6126 //coords-=facing*multiplier*50*scale;
6127 velocity += facing * multiplier * speed * 700 * scale * -1;
6128 velspeed = findLength(&velocity);
6129 if (velspeed > speed * 50 * scale) {
6130 velocity /= velspeed;
6131 velspeed = speed * 50 * scale;
6132 velocity *= velspeed;
6134 velocity.y += gravity * multiplier * 20;
6135 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6136 velspeed = findLength(&velocity);
6137 velocity = flatfacing * velspeed * -1;
6139 if (animTarget == dodgebackanim) {
6140 //coords-=facing*multiplier*50*scale;
6141 velocity += facing * multiplier * speed * 700 * scale * -1;
6142 velspeed = findLength(&velocity);
6143 if (velspeed > speed * 60 * scale) {
6144 velocity /= velspeed;
6145 velspeed = speed * 60 * scale;
6146 velocity *= velspeed;
6148 velocity.y += gravity * multiplier * 20;
6149 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6150 velspeed = findLength(&velocity);
6151 velocity = flatfacing * velspeed * -1;
6154 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6155 velspeed = findLength(&velocity);
6158 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6159 velocity.y += gravity * multiplier;
6162 if (animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6163 coords += velocity * multiplier;
6166 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6167 if (isFlip() && targetFrame().label == 7) {
6171 if (animTarget == jumpupanim) {
6173 animTarget = getIdle();
6180 pause_sound(whooshsound);
6181 OPENAL_SetVolume(channels[whooshsound], 0);
6184 if (animTarget == jumpdownanim || isFlip()) {
6188 animTarget = getLanding();
6189 emit_sound_at(landsound, coords, 128.);
6192 addEnvSound(coords);
6197 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6198 coords.y += gravity * multiplier * 2;
6200 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
6201 coords.y = terrain.getHeight(coords.x, coords.z);
6205 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)) {
6206 velspeed = findLength(&velocity);
6208 if (velspeed < multiplier * 300 * scale) {
6211 velocity -= velocity / velspeed * multiplier * 300 * scale;
6213 if (velspeed > 5 && (isLanding() || isLandhard())) {
6214 skiddingdelay += multiplier;
6215 if (skiddelay <= 0) {
6216 FootLand(leftfoot, .5);
6217 FootLand(rightfoot, .5);
6226 velspeed = findLength(&velocity);
6228 if (velspeed > 5 && (isLanding() || isLandhard())) {
6229 skiddingdelay += multiplier;
6230 if (skiddelay <= 0) {
6231 FootLand(leftfoot, .5);
6232 FootLand(rightfoot, .5);
6240 if (skiddingdelay < 0) {
6241 skiddingdelay += multiplier;
6243 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
6245 if (!onterrain || environment == grassyenvironment) {
6246 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
6248 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
6252 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
6253 terrainnormal = victim->coords - coords;
6254 Normalise(&terrainnormal);
6255 targetyaw = -asin(0 - terrainnormal.x);
6256 targetyaw *= 360 / 6.28;
6257 if (terrainnormal.z < 0) {
6258 targetyaw = 180 - targetyaw;
6260 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
6263 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
6264 targetyaw = victim->targetyaw;
6266 if (animTarget == rabbittacklinganim) {
6267 coords = victim->coords;
6270 skeleton.oldfree = skeleton.free;
6274 midterrain.x = terrain.size * terrain.scale / 2;
6275 midterrain.z = terrain.size * terrain.scale / 2;
6276 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
6278 tempposit = coords - midterrain;
6280 Normalise(&tempposit);
6281 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
6282 coords.x = tempposit.x + midterrain.x;
6283 coords.z = tempposit.z + midterrain.z;
6288 * inverse kinematics helper function
6290 void IKHelper(Person* p, float interp)
6292 XYZ point, change, change2;
6293 float heightleft, heightright;
6295 // TODO: implement localToWorld and worldToLocal
6296 // but keep in mind it won't be the same math if player is ragdolled or something
6297 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
6298 // then comb through code for places where to use it
6300 // point = localToWorld(jointPos(leftfoot))
6301 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
6302 // adjust height of foot
6303 heightleft = terrain.getHeight(point.x, point.z) + .04;
6304 point.y = heightleft;
6305 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
6306 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
6307 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
6308 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
6309 // move ankle along with foot
6310 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
6311 // average knee pos between old and new pos
6312 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
6314 // do same as above for right leg
6315 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
6316 heightright = terrain.getHeight(point.x, point.z) + .04;
6317 point.y = heightright;
6318 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
6319 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
6320 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
6321 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
6322 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
6324 // fix up skeleton now that we've moved body parts?
6325 p->skeleton.DoConstraints(&p->coords, &p->scale);
6332 int Person::DrawSkeleton()
6334 int oldplayerdetail;
6335 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6336 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6346 glAlphaFunc(GL_GREATER, 0.0001);
6348 float terrainheight;
6350 if (!isnormal(yaw)) {
6353 if (!isnormal(tilt)) {
6356 if (!isnormal(tilt2)) {
6359 oldplayerdetail = playerdetail;
6361 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6364 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6367 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6373 if (playerdetail != oldplayerdetail) {
6375 normalsupdatedelay = 0;
6377 static float updatedelaychange;
6378 static float morphness;
6379 static float framemult;
6381 skeleton.FindForwards();
6382 if (howactive == typesittingwall) {
6383 skeleton.specialforward[1] = 0;
6384 skeleton.specialforward[1].z = 1;
6390 static int weaponattachmuscle;
6391 static int weaponrotatemuscle;
6392 static XYZ weaponpoint;
6393 static int start, endthing;
6394 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6395 if (!isSleeping() && !isSitting()) {
6396 // TODO: give these meaningful names
6397 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6398 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard() || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6400 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6402 if (creature == wolftype) {
6407 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6408 IKHelper(this, target);
6409 if (creature == wolftype) {
6410 IKHelper(this, target);
6414 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6415 IKHelper(this, 1 - target);
6416 if (creature == wolftype) {
6417 IKHelper(this, 1 - target);
6422 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())) {
6425 targetheadyaw = -targetyaw;
6426 targetheadpitch = 0;
6427 if (Animation::animations[animTarget].attack == 3) {
6428 targetheadyaw += 180;
6431 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6432 skeleton.drawmodel.vertex[i] = 0;
6433 skeleton.drawmodel.vertex[i].y = 999;
6435 for (int i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6436 skeleton.drawmodellow.vertex[i] = 0;
6437 skeleton.drawmodellow.vertex[i].y = 999;
6439 for (int i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6440 skeleton.drawmodelclothes.vertex[i] = 0;
6441 skeleton.drawmodelclothes.vertex[i].y = 999;
6443 for (unsigned int i = 0; i < skeleton.muscles.size(); i++) {
6444 // convenience renames
6445 const int p1 = skeleton.muscles[i].parent1->label;
6446 const int p2 = skeleton.muscles[i].parent2->label;
6448 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6453 if (p1 == righthand || p2 == righthand) {
6454 morphness = righthandmorphness;
6455 start = righthandmorphstart;
6456 endthing = righthandmorphend;
6458 if (p1 == lefthand || p2 == lefthand) {
6459 morphness = lefthandmorphness;
6460 start = lefthandmorphstart;
6461 endthing = lefthandmorphend;
6463 if (p1 == head || p2 == head) {
6464 morphness = headmorphness;
6465 start = headmorphstart;
6466 endthing = headmorphend;
6468 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6469 morphness = chestmorphness;
6470 start = chestmorphstart;
6471 endthing = chestmorphend;
6473 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6474 morphness = tailmorphness;
6475 start = tailmorphstart;
6476 endthing = tailmorphend;
6479 skeleton.FindRotationMuscle(i, animTarget);
6481 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6482 glMatrixMode(GL_MODELVIEW);
6485 if (!skeleton.free) {
6486 glRotatef(tilt2, 1, 0, 0);
6488 if (!skeleton.free) {
6489 glRotatef(tilt, 0, 0, 1);
6492 glTranslatef(mid.x, mid.y, mid.z);
6494 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6495 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6497 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6498 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6500 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6501 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6503 if (playerdetail || skeleton.free == 3) {
6504 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6505 XYZ& v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6506 XYZ& v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6507 glMatrixMode(GL_MODELVIEW);
6509 if (p1 == abdomen || p2 == abdomen) {
6510 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(1).x,
6511 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(1).y,
6512 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(1).z);
6514 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6515 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(2).x,
6516 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(2).y,
6517 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(2).z);
6519 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6520 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(3).x,
6521 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(3).y,
6522 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(3).z);
6524 if (p1 == head || p2 == head) {
6525 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(0).x,
6526 (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(0).y,
6527 (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(0).z);
6529 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6530 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6531 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6532 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6536 if (!playerdetail || skeleton.free == 3) {
6537 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6538 XYZ& v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6539 glMatrixMode(GL_MODELVIEW);
6541 if (p1 == abdomen || p2 == abdomen) {
6542 glTranslatef(v0.x * getProportion(1).x,
6543 v0.y * getProportion(1).y,
6544 v0.z * getProportion(1).z);
6546 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6547 glTranslatef(v0.x * getProportion(2).x,
6548 v0.y * getProportion(2).y,
6549 v0.z * getProportion(2).z);
6551 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6552 glTranslatef(v0.x * getProportion(3).x,
6553 v0.y * getProportion(3).y,
6554 v0.z * getProportion(3).z);
6556 if (p1 == head || p2 == head) {
6557 glTranslatef(v0.x * getProportion(0).x,
6558 v0.y * getProportion(0).y,
6559 v0.z * getProportion(0).z);
6562 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6563 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6564 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6565 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6571 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6572 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6574 glMatrixMode(GL_MODELVIEW);
6577 if (!skeleton.free) {
6578 glRotatef(tilt2, 1, 0, 0);
6580 if (!skeleton.free) {
6581 glRotatef(tilt, 0, 0, 1);
6583 glTranslatef(mid.x, mid.y, mid.z);
6584 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6585 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6587 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6588 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6590 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6591 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6593 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6594 XYZ& v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6595 glMatrixMode(GL_MODELVIEW);
6597 if (p1 == abdomen || p2 == abdomen) {
6598 glTranslatef(v0.x * getProportion(1).x,
6599 v0.y * getProportion(1).y,
6600 v0.z * getProportion(1).z);
6602 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6603 glTranslatef(v0.x * getProportion(2).x,
6604 v0.y * getProportion(2).y,
6605 v0.z * getProportion(2).z);
6607 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6608 glTranslatef(v0.x * getProportion(3).x,
6609 v0.y * getProportion(3).y,
6610 v0.z * getProportion(3).z);
6612 if (p1 == head || p2 == head) {
6613 glTranslatef(v0.x * getProportion(0).x,
6614 v0.y * getProportion(0).y,
6615 v0.z * getProportion(0).z);
6617 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6618 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6619 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6620 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6625 updatedelay = 1 + (float)(Random() % 100) / 1000;
6627 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6628 normalsupdatedelay = 1;
6629 if (playerdetail || skeleton.free == 3) {
6630 skeleton.drawmodel.CalculateNormals(0);
6632 if (!playerdetail || skeleton.free == 3) {
6633 skeleton.drawmodellow.CalculateNormals(0);
6635 if (skeleton.clothes) {
6636 skeleton.drawmodelclothes.CalculateNormals(0);
6639 if (playerdetail || skeleton.free == 3) {
6640 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6642 if (!playerdetail || skeleton.free == 3) {
6643 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6645 if (skeleton.clothes) {
6646 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6651 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6652 if (updatedelaychange > -realmultiplier * 30) {
6653 updatedelaychange = -realmultiplier * 30;
6655 if (updatedelaychange > -framemult * 4) {
6656 updatedelaychange = -framemult * 4;
6658 if (skeleton.free == 1) {
6659 updatedelaychange *= 6;
6662 updatedelaychange *= 8;
6664 updatedelay += updatedelaychange;
6666 glMatrixMode(GL_MODELVIEW);
6668 glTranslatef(coords.x, coords.y - .02, coords.z);
6669 if (!skeleton.free) {
6670 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6671 glRotatef(yaw, 0, 1, 0);
6675 glColor4f(.4, 1, .4, 1);
6676 glDisable(GL_LIGHTING);
6677 glDisable(GL_TEXTURE_2D);
6680 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6681 XYZ& v0 = skeleton.drawmodel.vertex[i];
6682 glVertex3f(v0.x, v0.y, v0.z);
6689 for (unsigned int i = 0; i < skeleton.drawmodel.Triangles.size(); i++) {
6690 const XYZ& v0 = skeleton.drawmodel.getTriangleVertex(i, 0);
6691 const XYZ& v1 = skeleton.drawmodel.getTriangleVertex(i, 1);
6692 const XYZ& v2 = skeleton.drawmodel.getTriangleVertex(i, 2);
6693 glVertex3f(v0.x, v0.y, v0.z);
6694 glVertex3f(v1.x, v1.y, v1.z);
6695 glVertex3f(v1.x, v1.y, v1.z);
6696 glVertex3f(v2.x, v2.y, v2.z);
6697 glVertex3f(v2.x, v2.y, v2.z);
6698 glVertex3f(v0.x, v0.y, v0.z);
6705 terrainlight = terrain.getLighting(coords.x, coords.z);
6706 distance = distsq(&viewer, &coords);
6707 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6712 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6713 if (terrainheight < 1) {
6716 if (terrainheight > 1.7) {
6717 terrainheight = 1.7;
6720 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6721 glDisable(GL_BLEND);
6722 glAlphaFunc(GL_GREATER, 0.0001);
6723 glEnable(GL_TEXTURE_2D);
6725 glDisable(GL_TEXTURE_2D);
6726 glColor4f(.7, .35, 0, .5);
6728 glEnable(GL_LIGHTING);
6731 if (Tutorial::active && id != 0) {
6732 glColor4f(.7, .7, .7, 0.6);
6734 glEnable(GL_LIGHTING);
6736 if (canattack && cananger) {
6737 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6738 glDisable(GL_TEXTURE_2D);
6739 glColor4f(1, 0, 0, 0.8);
6742 glMatrixMode(GL_TEXTURE);
6744 glTranslatef(0, -smoketex, 0);
6745 glTranslatef(-smoketex, 0, 0);
6749 if (Tutorial::active && (id != 0)) {
6750 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6752 skeleton.drawmodel.draw();
6756 if (!playerdetail) {
6757 if (Tutorial::active && (id != 0)) {
6758 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6760 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6764 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed)) {
6765 if (Tutorial::active && id != 0) {
6767 glMatrixMode(GL_MODELVIEW);
6768 glEnable(GL_TEXTURE_2D);
6769 glColor4f(.7, .7, .7, 0.6);
6771 glEnable(GL_LIGHTING);
6773 if (canattack && cananger) {
6774 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6775 glDisable(GL_TEXTURE_2D);
6776 glColor4f(1, 0, 0, 0.8);
6779 glMatrixMode(GL_TEXTURE);
6781 glTranslatef(0, -smoketex * .6, 0);
6782 glTranslatef(smoketex * .6, 0, 0);
6785 if (Tutorial::active && (id != 0)) {
6786 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6788 skeleton.drawmodel.draw();
6792 if (!playerdetail) {
6793 if (Tutorial::active && (id != 0)) {
6794 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6796 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6802 if (Tutorial::active && id != 0) {
6804 glMatrixMode(GL_MODELVIEW);
6805 glEnable(GL_TEXTURE_2D);
6807 if (skeleton.clothes) {
6811 skeleton.drawmodelclothes.draw();
6814 skeleton.drawmodelclothes.drawimmediate();
6821 if (num_weapons > 0) {
6822 for (k = 0; k < num_weapons; k++) {
6823 int i = weaponids[k];
6824 if (weaponactive == k) {
6825 if (weapons[i].getType() != staff) {
6826 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6827 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6828 weaponattachmuscle = j;
6831 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6832 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) {
6833 weaponrotatemuscle = j;
6836 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6837 if (creature == wolftype) {
6838 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6841 if (weapons[i].getType() == staff) {
6842 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6843 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6844 weaponattachmuscle = j;
6847 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6848 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) {
6849 weaponrotatemuscle = j;
6852 //weaponpoint=jointPos(rightwrist);
6853 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6854 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6855 XYZ tempnormthing, vec1, vec2;
6856 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6857 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6858 CrossProduct(&vec1, &vec2, &tempnormthing);
6859 Normalise(&tempnormthing);
6860 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim) {
6861 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6865 if (weaponactive != k && weaponstuck != k) {
6866 if (weapons[i].getType() == knife) {
6867 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6869 if (weapons[i].getType() == sword) {
6870 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6872 if (weapons[i].getType() == staff) {
6873 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6875 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6876 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) {
6877 weaponrotatemuscle = j;
6881 if (weaponstuck == k) {
6882 if (weaponstuckwhere == 0) {
6883 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6885 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6887 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6888 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) {
6889 weaponrotatemuscle = j;
6893 if (skeleton.free) {
6894 weapons[i].position = weaponpoint * scale + coords;
6895 weapons[i].bigrotation = 0;
6896 weapons[i].bigtilt = 0;
6897 weapons[i].bigtilt2 = 0;
6899 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;
6900 weapons[i].bigrotation = yaw;
6901 weapons[i].bigtilt = tilt;
6902 weapons[i].bigtilt2 = tilt2;
6904 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6905 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6906 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6907 if (weaponactive == k) {
6908 if (weapons[i].getType() == knife) {
6909 weapons[i].smallrotation = 180;
6910 weapons[i].smallrotation2 = 0;
6911 if (isCrouch() || wasCrouch()) {
6912 weapons[i].smallrotation2 = 20;
6914 if (animTarget == hurtidleanim) {
6915 weapons[i].smallrotation2 = 50;
6917 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6918 XYZ temppoint1, temppoint2;
6921 temppoint1 = jointPos(righthand);
6922 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6923 distance = findDistance(&temppoint1, &temppoint2);
6924 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6925 weapons[i].rotation2 *= 360 / 6.28;
6928 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6929 weapons[i].rotation1 *= 360 / 6.28;
6930 weapons[i].rotation3 = 0;
6931 weapons[i].smallrotation = -90;
6932 weapons[i].smallrotation2 = 0;
6933 if (temppoint1.x > temppoint2.x) {
6934 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6937 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6938 XYZ temppoint1, temppoint2;
6941 temppoint1 = jointPos(righthand);
6942 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6943 distance = findDistance(&temppoint1, &temppoint2);
6944 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6945 weapons[i].rotation2 *= 360 / 6.28;
6948 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6949 weapons[i].rotation1 *= 360 / 6.28;
6950 weapons[i].rotation3 = 0;
6951 weapons[i].smallrotation = 90;
6952 weapons[i].smallrotation2 = 0;
6953 if (temppoint1.x > temppoint2.x) {
6954 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6957 if (animTarget == knifethrowanim) {
6958 weapons[i].smallrotation = 90;
6959 //weapons[i].smallrotation2=-90;
6960 weapons[i].smallrotation2 = 0;
6961 weapons[i].rotation1 = 0;
6962 weapons[i].rotation2 = 0;
6963 weapons[i].rotation3 = 0;
6965 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6966 weapons[i].smallrotation = -90;
6967 weapons[i].rotation1 = 0;
6968 weapons[i].rotation2 = 0;
6969 weapons[i].rotation3 = 0;
6972 if (weapons[i].getType() == sword) {
6973 weapons[i].smallrotation = 0;
6974 weapons[i].smallrotation2 = 0;
6975 if (animTarget == knifethrowanim) {
6976 weapons[i].smallrotation = -90;
6977 weapons[i].smallrotation2 = 0;
6978 weapons[i].rotation1 = 0;
6979 weapons[i].rotation2 = 0;
6980 weapons[i].rotation3 = 0;
6982 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)) {
6983 XYZ temppoint1, temppoint2;
6986 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6987 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6988 distance = findDistance(&temppoint1, &temppoint2);
6989 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6990 weapons[i].rotation2 *= 360 / 6.28;
6993 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6994 weapons[i].rotation1 *= 360 / 6.28;
6995 weapons[i].rotation3 = 0;
6996 weapons[i].smallrotation = 90;
6997 weapons[i].smallrotation2 = 0;
6998 if (temppoint1.x > temppoint2.x) {
6999 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7003 if (weapons[i].getType() == staff) {
7004 weapons[i].smallrotation = 100;
7005 weapons[i].smallrotation2 = 0;
7006 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
7007 XYZ temppoint1, temppoint2;
7010 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
7011 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7012 distance = findDistance(&temppoint1, &temppoint2);
7013 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7014 weapons[i].rotation2 *= 360 / 6.28;
7017 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7018 weapons[i].rotation1 *= 360 / 6.28;
7019 weapons[i].rotation3 = 0;
7020 weapons[i].smallrotation = 90;
7021 weapons[i].smallrotation2 = 0;
7022 if (temppoint1.x > temppoint2.x) {
7023 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7028 if (weaponactive != k && weaponstuck != k) {
7029 if (weapons[i].getType() == knife) {
7030 weapons[i].smallrotation = -70;
7031 weapons[i].smallrotation2 = 10;
7033 if (weapons[i].getType() == sword) {
7034 weapons[i].smallrotation = -100;
7035 weapons[i].smallrotation2 = -8;
7037 if (weapons[i].getType() == staff) {
7038 weapons[i].smallrotation = -100;
7039 weapons[i].smallrotation2 = -8;
7042 if (weaponstuck == k) {
7043 if (weaponstuckwhere == 0) {
7044 weapons[i].smallrotation = 180;
7046 weapons[i].smallrotation = 0;
7048 weapons[i].smallrotation2 = 10;
7055 if (skeleton.free) {
7058 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump()) {
7061 if (animCurrent != animTarget) {
7064 if (skeleton.free == 2) {
7073 int Person::SphereCheck(XYZ* p1, float radius, XYZ* p, XYZ* move, float* rotate, Model* model)
7075 static float distance;
7076 static float olddistance;
7077 static int intersecting;
7078 static int firstintersecting;
7081 static XYZ start, end;
7082 static float slopethreshold = -.4;
7084 firstintersecting = -1;
7088 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius) {
7092 *p1 = DoRotation(*p1, 0, -*rotate, 0);
7094 for (int i = 0; i < 4; i++) {
7095 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7096 if (model->Triangles[j].facenormal.y <= slopethreshold) {
7098 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)));
7099 if (distance < radius) {
7100 point = *p1 - model->Triangles[j].facenormal * distance;
7101 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]])) {
7104 if (!intersecting) {
7105 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7106 &model->vertex[model->Triangles[j].vertex[1]],
7109 if (!intersecting) {
7110 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
7111 &model->vertex[model->Triangles[j].vertex[2]],
7114 if (!intersecting) {
7115 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7116 &model->vertex[model->Triangles[j].vertex[2]],
7120 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7124 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)) {
7125 p1->y = point.y + radius;
7126 if ((animTarget == jumpdownanim || isFlip())) {
7127 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4)) {
7131 if (animTarget == jumpupanim) {
7133 animTarget = getIdle();
7140 pause_sound(whooshsound);
7141 OPENAL_SetVolume(channels[whooshsound], 0);
7144 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
7148 animTarget = getLanding();
7149 emit_sound_at(landsound, coords, 128.);
7152 addEnvSound(coords);
7159 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7160 olddistance = distance;
7161 firstintersecting = j;
7166 for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7167 if (model->Triangles[j].facenormal.y > slopethreshold) {
7170 start.y -= radius / 4;
7171 XYZ& v0 = model->vertex[model->Triangles[j].vertex[0]];
7172 XYZ& v1 = model->vertex[model->Triangles[j].vertex[1]];
7173 XYZ& v2 = model->vertex[model->Triangles[j].vertex[2]];
7174 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)));
7175 if (distance < radius * .5) {
7176 point = start - model->Triangles[j].facenormal * distance;
7177 if (PointInTriangle(&point, model->Triangles[j].facenormal, &v0, &v1, &v2)) {
7180 if (!intersecting) {
7181 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
7183 if (!intersecting) {
7184 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7186 if (!intersecting) {
7187 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7190 if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7191 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
7193 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;
7194 if (findLengthfast(&start) < findLengthfast(&velocity)) {
7198 *p1 += model->Triangles[j].facenormal * (distance - radius * .5);
7201 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7202 olddistance = distance;
7203 firstintersecting = j;
7210 *p = DoRotation(*p, 0, *rotate, 0);
7214 *p1 = DoRotation(*p1, 0, *rotate, 0);
7217 return firstintersecting;
7220 int findPathDist(int start, int end)
7225 unsigned int smallestcount = 1000;
7226 for (char i = 0; i < 50; i++) {
7227 unsigned int count = 0;
7232 while (last != end && count < 30) {
7234 for (int j = 0; j < Game::numpathpoints; j++) {
7235 if (j != last && j != last2 && j != last3 && j != last4) {
7237 if (Game::numpathpointconnect[j]) {
7238 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7239 if (Game::pathpointconnect[j][k] == last) {
7245 if (Game::numpathpointconnect[last]) {
7246 for (int k = 0; k < Game::numpathpointconnect[last]; k++) {
7247 if (Game::pathpointconnect[last][k] == j) {
7254 if (closest == -1 || Random() % 2 == 0) {
7266 if (count < smallestcount) {
7267 smallestcount = count;
7270 return smallestcount;
7273 void Person::takeWeapon(int weaponId)
7276 weapons[weaponId].owner = id;
7277 if (num_weapons > 0) {
7278 weaponids[num_weapons] = weaponids[0];
7281 weaponids[0] = weaponId;
7284 void Person::addClothes()
7286 if (numclothes > 0) {
7287 for (int i = 0; i < numclothes; i++) {
7294 bool Person::addClothes(const int& clothesId)
7297 const std::string fileName = clothes[clothesId];
7299 GLubyte* array = &skeleton.skinText[0];
7303 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
7308 float tintr = clothestintr[clothesId];
7309 float tintg = clothestintg[clothesId];
7310 float tintb = clothestintb[clothesId];
7332 int bytesPerPixel = texture.bpp / 8;
7336 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
7337 if (bytesPerPixel == 3) {
7339 } else if ((i + 1) % 4 == 0) {
7340 alphanum = texture.data[i];
7342 if ((i + 1) % 4 || bytesPerPixel == 3) {
7344 texture.data[i] *= tintr;
7347 texture.data[i] *= tintg;
7350 texture.data[i] *= tintb;
7352 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
7364 if (aitype != playercontrolled && !Dialog::inDialog()) {
7366 //disable movement in editor
7367 if (Game::editorenabled) {
7372 if (distsqflat(&Person::players[0]->coords, &coords) < 30 &&
7373 Person::players[0]->coords.y > coords.y + 2 &&
7374 !Person::players[0]->onterrain) {
7379 if (aitype == pathfindtype) {
7380 if (finalpathfindpoint == -1) {
7381 float closestdistance;
7382 float tempdist = 0.0f;
7386 closestdistance = -1;
7387 for (int j = 0; j < Game::numpathpoints; j++) {
7388 if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) {
7389 closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]);
7391 finaltarget = Game::pathpoint[j];
7394 finalpathfindpoint = closest;
7395 for (int j = 0; j < Game::numpathpoints; j++) {
7396 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7397 DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7398 if (sq(tempdist) < closestdistance) {
7399 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7400 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7401 closestdistance = sq(tempdist);
7403 finaltarget = colpoint;
7408 finalpathfindpoint = closest;
7410 if (targetpathfindpoint == -1) {
7411 float closestdistance;
7412 float tempdist = 0.0f;
7416 closestdistance = -1;
7417 if (lastpathfindpoint == -1) {
7418 for (int j = 0; j < Game::numpathpoints; j++) {
7419 if (j != lastpathfindpoint) {
7420 if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) {
7421 closestdistance = distsq(&coords, &Game::pathpoint[j]);
7426 targetpathfindpoint = closest;
7427 for (int j = 0; j < Game::numpathpoints; j++) {
7428 if (j != lastpathfindpoint) {
7429 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7430 DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7431 if (sq(tempdist) < closestdistance) {
7432 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7433 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7434 closestdistance = sq(tempdist);
7441 targetpathfindpoint = closest;
7443 for (int j = 0; j < Game::numpathpoints; j++) {
7444 if (j != lastpathfindpoint &&
7445 j != lastpathfindpoint2 &&
7446 j != lastpathfindpoint3 &&
7447 j != lastpathfindpoint4) {
7449 if (Game::numpathpointconnect[j]) {
7450 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7451 if (Game::pathpointconnect[j][k] == lastpathfindpoint) {
7457 if (Game::numpathpointconnect[lastpathfindpoint]) {
7458 for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++) {
7459 if (Game::pathpointconnect[lastpathfindpoint][k] == j) {
7466 tempdist = findPathDist(j, finalpathfindpoint);
7467 if (closest == -1 || tempdist < closestdistance) {
7468 closestdistance = tempdist;
7474 targetpathfindpoint = closest;
7477 losupdatedelay -= multiplier;
7479 targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]);
7480 lookyaw = targetyaw;
7482 //reached target point
7483 if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) {
7484 lastpathfindpoint4 = lastpathfindpoint3;
7485 lastpathfindpoint3 = lastpathfindpoint2;
7486 lastpathfindpoint2 = lastpathfindpoint;
7487 lastpathfindpoint = targetpathfindpoint;
7488 if (lastpathfindpoint2 == -1) {
7489 lastpathfindpoint2 = lastpathfindpoint;
7491 if (lastpathfindpoint3 == -1) {
7492 lastpathfindpoint3 = lastpathfindpoint2;
7494 if (lastpathfindpoint4 == -1) {
7495 lastpathfindpoint4 = lastpathfindpoint3;
7497 targetpathfindpoint = -1;
7499 if (distsqflat(&coords, &finalfinaltarget) <
7500 distsqflat(&coords, &finaltarget) ||
7501 distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) ||
7502 lastpathfindpoint == finalpathfindpoint) {
7503 aitype = passivetype;
7514 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7515 targetyaw += 90 * (whichdirection * 2 - 1);
7518 if (collided < 1 || animTarget != jumpupanim) {
7521 if ((collided > .8 && jumppower >= 5)) {
7525 if ((!Tutorial::active || cananger) &&
7527 !Person::players[0]->dead &&
7528 distsq(&coords, &Person::players[0]->coords) < 400 &&
7530 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7531 Animation::animations[Person::players[0]->animTarget].height != lowheight &&
7532 !Game::editorenabled &&
7533 (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain)) {
7534 aitype = attacktypecutoff;
7536 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7537 Animation::animations[Person::players[0]->animTarget].height == highheight &&
7538 !Game::editorenabled) {
7539 aitype = attacktypecutoff;
7542 if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7543 losupdatedelay = .2;
7544 for (unsigned j = 0; j < Person::players.size(); j++) {
7545 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7546 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7547 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7548 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7549 if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain) {
7550 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) ||
7551 (Person::players[j]->animTarget == hanganim &&
7552 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7553 aitype = searchtype;
7555 lastseen = Person::players[j]->coords;
7566 if (aitype == attacktypecutoff && Game::musictype != 2) {
7567 if (creature != wolftype) {
7574 if (aitype != passivetype && Game::leveltime > .5) {
7575 howactive = typeactive;
7578 if (aitype == passivetype) {
7579 aiupdatedelay -= multiplier;
7580 losupdatedelay -= multiplier;
7581 lastseentime += multiplier;
7582 pausetime -= multiplier;
7583 if (lastseentime > 1) {
7587 if (aiupdatedelay < 0) {
7588 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7589 targetyaw = roughDirectionTo(coords, waypoints[waypoint]);
7590 lookyaw = targetyaw;
7591 aiupdatedelay = .05;
7593 if (distsqflat(&coords, &waypoints[waypoint]) < 1) {
7594 if (waypointtype[waypoint] == wppause) {
7598 if (waypoint > numwaypoints - 1) {
7604 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7616 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7617 if (!avoidsomething) {
7618 targetyaw += 90 * (whichdirection * 2 - 1);
7620 XYZ leftpos, rightpos;
7621 float leftdist, rightdist;
7622 leftpos = coords + DoRotation(facing, 0, 90, 0);
7623 rightpos = coords - DoRotation(facing, 0, 90, 0);
7624 leftdist = distsq(&leftpos, &avoidwhere);
7625 rightdist = distsq(&rightpos, &avoidwhere);
7626 if (leftdist < rightdist) {
7634 if (collided < 1 || animTarget != jumpupanim) {
7637 if ((collided > .8 && jumppower >= 5)) {
7642 if (!Game::editorenabled) {
7643 if (howactive <= typesleeping) {
7644 if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile) {
7645 for (int j = 0; j < numenvsounds; j++) {
7646 float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
7647 if (vol > 0 && distsq(&coords, &envsound[j]) < 2 * (vol + vol * (creature == rabbittype) * 3)) {
7648 aitype = attacktypecutoff;
7654 if (aitype != passivetype) {
7655 if (howactive == typesleeping) {
7656 setTargetAnimation(getupfromfrontanim);
7658 howactive = typeactive;
7662 if (howactive < typesleeping &&
7663 ((!Tutorial::active || cananger) && hostile) &&
7664 !Person::players[0]->dead &&
7665 distsq(&coords, &Person::players[0]->coords) < 400 &&
7667 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7668 Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled) {
7669 aitype = attacktypecutoff;
7671 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7672 Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled) {
7673 aitype = attacktypecutoff;
7677 if (creature == wolftype) {
7679 for (unsigned j = 0; j < Person::players.size(); j++) {
7680 if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
7681 float smelldistance = 50;
7682 if (j == 0 && Person::players[j]->num_weapons > 0) {
7683 if (weapons[Person::players[j]->weaponids[0]].bloody) {
7684 smelldistance = 100;
7686 if (Person::players[j]->num_weapons == 2) {
7687 if (weapons[Person::players[j]->weaponids[1]].bloody) {
7688 smelldistance = 100;
7693 smelldistance = 100;
7695 windsmell = windvector;
7696 Normalise(&windsmell);
7697 windsmell = windsmell * 2 + Person::players[j]->coords;
7698 if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled) {
7699 aitype = attacktypecutoff;
7705 if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7706 losupdatedelay = .2;
7707 for (unsigned j = 0; j < Person::players.size(); j++) {
7708 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7709 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7710 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7711 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7712 if ((-1 == Object::checkcollide(
7713 DoRotation(jointPos(head), 0, yaw, 0) *
7716 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0) *
7717 Person::players[j]->scale +
7718 Person::players[j]->coords) &&
7719 !Person::players[j]->isWallJump()) ||
7720 (Person::players[j]->animTarget == hanganim &&
7721 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7723 if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight) {
7732 if (lastseentime <= 0) {
7733 aitype = searchtype;
7735 lastseen = Person::players[j]->coords;
7743 if (aitype == attacktypecutoff && Game::musictype != 2) {
7744 if (creature != wolftype) {
7748 if (creature == wolftype) {
7758 if (aitype == searchtype) {
7759 aiupdatedelay -= multiplier;
7760 losupdatedelay -= multiplier;
7762 lastseentime -= multiplier;
7764 lastchecktime -= multiplier;
7766 if (isRun() && !onground) {
7767 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7768 XYZ test2 = coords + facing;
7770 XYZ test = coords + facing;
7772 j = Object::checkcollide(test2, test, laststanding);
7774 j = Object::checkcollide(test2, test);
7778 setTargetAnimation(getStop());
7781 //aitype=passivetype;
7782 aitype = pathfindtype;
7783 finalfinaltarget = waypoints[waypoint];
7784 finalpathfindpoint = -1;
7785 targetpathfindpoint = -1;
7786 lastpathfindpoint = -1;
7787 lastpathfindpoint2 = -1;
7788 lastpathfindpoint3 = -1;
7789 lastpathfindpoint4 = -1;
7795 //check out last seen location
7796 if (aiupdatedelay < 0) {
7797 targetyaw = roughDirectionTo(coords, lastseen);
7798 lookyaw = targetyaw;
7799 aiupdatedelay = .05;
7802 if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) {
7805 lastseen.x += (float(Random() % 100) - 50) / 25;
7806 lastseen.z += (float(Random() % 100) - 50) / 25;
7817 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7818 if (!avoidsomething) {
7819 targetyaw += 90 * (whichdirection * 2 - 1);
7821 XYZ leftpos, rightpos;
7822 float leftdist, rightdist;
7823 leftpos = coords + DoRotation(facing, 0, 90, 0);
7824 rightpos = coords - DoRotation(facing, 0, 90, 0);
7825 leftdist = distsq(&leftpos, &avoidwhere);
7826 rightdist = distsq(&rightpos, &avoidwhere);
7827 if (leftdist < rightdist) {
7835 if (collided < 1 || animTarget != jumpupanim) {
7838 if ((collided > .8 && jumppower >= 5)) {
7842 if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile)) {
7843 for (int k = 0; k < numenvsounds; k++) {
7844 if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) {
7845 aitype = attacktypecutoff;
7850 if (!Person::players[0]->dead &&
7851 losupdatedelay < 0 &&
7852 !Game::editorenabled &&
7854 ((!Tutorial::active || cananger) && hostile)) {
7855 losupdatedelay = .2;
7856 if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) {
7857 aitype = attacktypecutoff;
7860 if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight) {
7861 //TODO: factor out canSeePlayer()
7862 if (distsq(&coords, &Person::players[0]->coords) < 400) {
7863 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
7864 if ((Object::checkcollide(
7865 DoRotation(jointPos(head), 0, yaw, 0) *
7868 DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0) *
7869 Person::players[0]->scale +
7870 Person::players[0]->coords) == -1) ||
7871 (Person::players[0]->animTarget == hanganim && normaldotproduct(Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) {
7872 /* //TODO: changed j to 0 on a whim, make sure this is correct
7873 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
7874 Person::players[j]->facing,coords-Person::players[j]->coords)<0)
7876 aitype = attacktypecutoff;
7884 if (lastseentime < 0) {
7885 //aitype=passivetype;
7887 aitype = pathfindtype;
7888 finalfinaltarget = waypoints[waypoint];
7889 finalpathfindpoint = -1;
7890 targetpathfindpoint = -1;
7891 lastpathfindpoint = -1;
7892 lastpathfindpoint2 = -1;
7893 lastpathfindpoint3 = -1;
7894 lastpathfindpoint4 = -1;
7898 if (aitype != gethelptype) {
7902 //get help from buddies
7903 if (aitype == gethelptype) {
7904 runninghowlong += multiplier;
7905 aiupdatedelay -= multiplier;
7907 if (aiupdatedelay < 0 || ally == 0) {
7911 //TODO: factor out closest search somehow
7914 float closestdist = -1;
7915 for (unsigned k = 0; k < Person::players.size(); k++) {
7916 if ((k != id) && (k != 0) && !Person::players[k]->dead &&
7917 (Person::players[k]->howactive < typedead1) &&
7918 !Person::players[k]->skeleton.free &&
7919 (Person::players[k]->aitype == passivetype)) {
7920 float distance = distsq(&coords, &Person::players[k]->coords);
7921 if (closestdist == -1 || distance < closestdist) {
7922 closestdist = distance;
7927 if (closest != -1) {
7932 lastseen = Person::players[0]->coords;
7938 XYZ facing = coords;
7939 XYZ flatfacing = Person::players[ally]->coords;
7940 facing.y += jointPos(head).y * scale;
7941 flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale;
7942 if (-1 != Object::checkcollide(facing, flatfacing)) {
7946 //no available ally, run back to player
7948 Person::players[ally]->skeleton.free ||
7949 Person::players[ally]->aitype != passivetype ||
7950 lastseentime <= 0) {
7951 aitype = searchtype;
7957 targetyaw = roughDirectionTo(coords, Person::players[ally]->coords);
7958 lookyaw = targetyaw;
7959 aiupdatedelay = .05;
7962 if (distsqflat(&coords, &Person::players[ally]->coords) < 3) {
7963 aitype = searchtype;
7965 Person::players[ally]->aitype = searchtype;
7966 if (Person::players[ally]->lastseentime < lastseentime) {
7967 Person::players[ally]->lastseen = lastseen;
7968 Person::players[ally]->lastseentime = lastseentime;
7969 Person::players[ally]->lastchecktime = lastchecktime;
7973 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7974 if (!avoidsomething) {
7975 targetyaw += 90 * (whichdirection * 2 - 1);
7977 XYZ leftpos, rightpos;
7978 float leftdist, rightdist;
7979 leftpos = coords + DoRotation(facing, 0, 90, 0);
7980 rightpos = coords - DoRotation(facing, 0, 90, 0);
7981 leftdist = distsq(&leftpos, &avoidwhere);
7982 rightdist = distsq(&rightpos, &avoidwhere);
7983 if (leftdist < rightdist) {
7998 if (collided < 1 || animTarget != jumpupanim) {
8001 if (collided > .8 && jumppower >= 5) {
8006 //retreiving a weapon on the ground
8007 if (aitype == getweapontype) {
8008 aiupdatedelay -= multiplier;
8009 lastchecktime -= multiplier;
8011 if (aiupdatedelay < 0) {
8017 float closestdist = -1;
8018 for (unsigned k = 0; k < weapons.size(); k++) {
8019 if (weapons[k].owner == -1) {
8020 float distance = distsq(&coords, &weapons[k].position);
8021 if (closestdist == -1 || distance < closestdist) {
8022 closestdist = distance;
8027 if (closest != -1) {
8036 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile)) {
8037 if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) {
8038 aitype = attacktypecutoff;
8042 if (!Person::players[0]->dead) {
8044 if (weapons[ally].owner != -1 ||
8045 distsq(&coords, &weapons[ally].position) > 16) {
8046 aitype = attacktypecutoff;
8049 //TODO: factor these out as moveToward()
8050 targetyaw = roughDirectionTo(coords, weapons[ally].position);
8051 lookyaw = targetyaw;
8052 aiupdatedelay = .05;
8055 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8056 if (!avoidsomething) {
8057 targetyaw += 90 * (whichdirection * 2 - 1);
8059 XYZ leftpos, rightpos;
8060 float leftdist, rightdist;
8061 leftpos = coords + DoRotation(facing, 0, 90, 0);
8062 rightpos = coords - DoRotation(facing, 0, 90, 0);
8063 leftdist = distsq(&leftpos, &avoidwhere);
8064 rightdist = distsq(&rightpos, &avoidwhere);
8065 if (leftdist < rightdist) {
8081 if (animTarget != crouchremoveknifeanim &&
8082 animTarget != removeknifeanim) {
8083 throwtogglekeydown = 0;
8087 if (collided < 1 || animTarget != jumpupanim) {
8090 if ((collided > .8 && jumppower >= 5)) {
8095 if (aitype == attacktypecutoff) {
8096 aiupdatedelay -= multiplier;
8097 //dodge or reverse rabbit kicks, knife throws, flips
8098 if (damage < damagetolerance * 2 / 3) {
8099 if ((Person::players[0]->animTarget == rabbitkickanim ||
8100 Person::players[0]->animTarget == knifethrowanim ||
8101 (Person::players[0]->isFlip() &&
8102 normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) &&
8103 !Person::players[0]->skeleton.free &&
8104 (aiupdatedelay < .1)) {
8109 if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
8110 if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
8111 if (isIdle() || isCrouch() || isRun() || isFlip()) {
8112 if (abs(Random() % 2) == 0) {
8113 setTargetAnimation(backhandspringanim);
8115 setTargetAnimation(rollanim);
8117 targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
8120 if (animTarget == jumpupanim || animTarget == jumpdownanim) {
8121 setTargetAnimation(flipanim);
8126 aiupdatedelay = .02;
8129 //get confused by flips
8130 if (Person::players[0]->isFlip() &&
8131 !Person::players[0]->skeleton.free &&
8132 Person::players[0]->animTarget != walljumprightkickanim &&
8133 Person::players[0]->animTarget != walljumpleftkickanim) {
8134 if (distsq(&Person::players[0]->coords, &coords) < 25) {
8135 if ((1 - damage / damagetolerance) > .5) {
8140 //go for weapon on the ground
8141 if (wentforweapon < 3) {
8142 for (unsigned k = 0; k < weapons.size(); k++) {
8143 if (creature != wolftype) {
8144 if (num_weapons == 0 &&
8145 weapons[k].owner == -1 &&
8146 weapons[k].velocity.x == 0 &&
8147 weapons[k].velocity.z == 0 &&
8148 weapons[k].velocity.y == 0) {
8149 if (distsq(&coords, &weapons[k].position) < 16) {
8152 aitype = getweapontype;
8159 //dodge/reverse walljump kicks
8160 if (damage < damagetolerance / 2) {
8161 if (Animation::animations[animTarget].height != highheight) {
8162 if (damage < damagetolerance * .5 &&
8163 ((Person::players[0]->animTarget == walljumprightkickanim ||
8164 Person::players[0]->animTarget == walljumpleftkickanim) &&
8165 ((aiupdatedelay < .15 &&
8167 (aiupdatedelay < .08 &&
8168 difficulty != 2)))) {
8173 //walked off a ledge (?)
8174 if (isRun() && !onground) {
8175 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
8176 XYZ test2 = coords + facing;
8178 XYZ test = coords + facing;
8180 j = Object::checkcollide(test2, test, laststanding);
8182 j = Object::checkcollide(test2, test);
8186 setTargetAnimation(getStop());
8189 aitype = pathfindtype;
8190 finalfinaltarget = waypoints[waypoint];
8191 finalpathfindpoint = -1;
8192 targetpathfindpoint = -1;
8193 lastpathfindpoint = -1;
8194 lastpathfindpoint2 = -1;
8195 lastpathfindpoint3 = -1;
8196 lastpathfindpoint4 = -1;
8202 //lose sight of player in the air (?)
8203 if (Person::players[0]->coords.y > coords.y + 5 &&
8204 Animation::animations[Person::players[0]->animTarget].height != highheight &&
8205 !Person::players[0]->onterrain) {
8206 aitype = pathfindtype;
8207 finalfinaltarget = waypoints[waypoint];
8208 finalpathfindpoint = -1;
8209 targetpathfindpoint = -1;
8210 lastpathfindpoint = -1;
8211 lastpathfindpoint2 = -1;
8212 lastpathfindpoint3 = -1;
8213 lastpathfindpoint4 = -1;
8215 //it's time to think (?)
8216 if (aiupdatedelay < 0 &&
8217 !Animation::animations[animTarget].attack &&
8218 animTarget != staggerbackhighanim &&
8219 animTarget != staggerbackhardanim &&
8220 animTarget != backhandspringanim &&
8221 animTarget != dodgebackanim) {
8223 if (weaponactive == -1 && num_weapons > 0) {
8224 drawkeydown = Random() % 2;
8228 rabbitkickenabled = Random() % 2;
8230 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
8231 XYZ targetpoint = Person::players[0]->coords;
8232 float vellength = findLength(&velocity);
8233 if (vellength != 0 &&
8234 distsq(&Person::players[0]->coords, &coords) < distsq(&rotatetarget, &coords)) {
8235 targetpoint += Person::players[0]->velocity *
8236 findDistance(&Person::players[0]->coords, &coords) / vellength;
8238 targetyaw = roughDirectionTo(coords, targetpoint);
8239 lookyaw = targetyaw;
8240 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
8242 if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1)) {
8244 } else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
8245 distsq(&coords, &Person::players[0]->coords) < 9) &&
8246 Person::players[0]->weaponactive != -1) {
8248 } else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0)) {
8253 //chill out around the corpse
8254 if (Person::players[0]->dead) {
8256 if (Random() % 10 == 0) {
8259 if (Random() % 100 == 0) {
8260 aitype = pathfindtype;
8261 finalfinaltarget = waypoints[waypoint];
8262 finalpathfindpoint = -1;
8263 targetpathfindpoint = -1;
8264 lastpathfindpoint = -1;
8265 lastpathfindpoint2 = -1;
8266 lastpathfindpoint3 = -1;
8267 lastpathfindpoint4 = -1;
8276 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8277 targetyaw += 90 * (whichdirection * 2 - 1);
8280 if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype) {
8285 if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7) {
8290 if (aitype != playercontrolled &&
8295 for (unsigned j = 0; j < Person::players.size(); j++) {
8296 if (j != id && !Person::players[j]->skeleton.free &&
8297 Person::players[j]->hasvictim &&
8298 (Tutorial::active && reversaltrain ||
8299 Random() % 2 == 0 && difficulty == 2 ||
8300 Random() % 4 == 0 && difficulty == 1 ||
8301 Random() % 8 == 0 && difficulty == 0 ||
8302 Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
8303 Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
8304 (Random() % 2 == 0 || difficulty == 2) ||
8305 (isIdle() || isRun()) &&
8306 Person::players[j]->weaponactive != -1 ||
8307 Person::players[j]->animTarget == swordslashanim &&
8308 weaponactive != -1 ||
8309 Person::players[j]->animTarget == staffhitanim ||
8310 Person::players[j]->animTarget == staffspinhitanim)) {
8311 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
8312 Person::players[j]->victim == Person::players[id] &&
8313 (Person::players[j]->animTarget == sweepanim ||
8314 Person::players[j]->animTarget == spinkickanim ||
8315 Person::players[j]->animTarget == staffhitanim ||
8316 Person::players[j]->animTarget == staffspinhitanim ||
8317 Person::players[j]->animTarget == winduppunchanim ||
8318 Person::players[j]->animTarget == upunchanim ||
8319 Person::players[j]->animTarget == wolfslapanim ||
8320 Person::players[j]->animTarget == knifeslashstartanim ||
8321 Person::players[j]->animTarget == swordslashanim &&
8322 (distsq(&Person::players[j]->coords, &coords) < 2 ||
8323 weaponactive != -1))) {
8333 Person::players[target]->Reverse();
8340 if (collided > .8 && jumppower >= 5 ||
8341 distsq(&coords, &Person::players[0]->coords) > 400 &&
8343 creature == rabbittype) {
8346 //TODO: why are we controlling the human?
8347 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
8348 Person::players[0]->jumpkeydown = 0;
8350 if (Person::players[0]->animTarget == jumpdownanim &&
8351 distsq(&Person::players[0]->coords, &coords) < 40) {
8358 if (Tutorial::active) {
8364 XYZ facing = coords;
8365 XYZ flatfacing = Person::players[0]->coords;
8366 facing.y += jointPos(head).y * scale;
8367 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
8368 if (occluded >= 2) {
8369 if (-1 != Object::checkcollide(facing, flatfacing)) {
8373 if (lastseentime <= 0 &&
8374 (creature != wolftype ||
8375 weaponstuck == -1)) {
8376 aitype = searchtype;
8378 lastseen = Person::players[0]->coords;
8387 if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
8388 (aitype == attacktypecutoff ||
8389 aitype == searchtype)) {
8390 if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
8391 XYZ test = Person::players[0]->coords;
8393 if (-1 == Object::checkcollide(Person::players[0]->coords, test)) {
8399 if (aitype == passivetype && !(numwaypoints > 1) ||
8401 pause && damage > superpermanentdamage) {
8420 XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0);
8421 facing = flatfacing;
8423 if (aitype == attacktypecutoff) {
8424 targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
8425 targetheadpitch = pitchTo(coords, Person::players[0]->coords);
8426 } else if (howactive >= typesleeping) {
8427 targetheadyaw = targetyaw;
8428 targetheadpitch = 0;
8430 if (interestdelay <= 0) {
8431 interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
8432 headtarget = coords;
8433 headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
8434 headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
8435 headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
8436 headtarget += facing * 1.5;
8438 targetheadyaw = 180 - roughDirectionTo(coords, headtarget);
8439 targetheadpitch = pitchTo(coords, headtarget);